From fa6d060bf8446e6f8bbc60222f79833a31bb9ab9 Mon Sep 17 00:00:00 2001 From: Alan Date: Fri, 24 Jul 2026 15:40:24 -0400 Subject: [PATCH] Migrate transfer valve, assembly holder, and chem grenade to the new attack chain. (#32262) * Add transfer valve to the new attack chain. * Apply suggestions from CRUNCH review Co-authored-by: CRUNCH <143041327+CRUNCH-Borg@users.noreply.github.com> Signed-off-by: Alan * Update assembly messages, migrate assembly holder and chem grenade. * Fix onetankbomb gas analysis. --------- Signed-off-by: Alan Co-authored-by: CRUNCH <143041327+CRUNCH-Borg@users.noreply.github.com> --- .../objects/items/devices/transfer_valve.dm | 88 ++++++++++--------- .../items/weapons/grenades/chem_grenade.dm | 4 +- code/modules/assembly/assembly.dm | 8 +- code/modules/assembly/assembly_holder.dm | 49 ++++++----- code/modules/assembly/bomb.dm | 70 ++++++++------- code/modules/assembly/mousetrap.dm | 27 ++++-- 6 files changed, 140 insertions(+), 106 deletions(-) diff --git a/code/game/objects/items/devices/transfer_valve.dm b/code/game/objects/items/devices/transfer_valve.dm index 8c1faf44a9c..6035ad49e58 100644 --- a/code/game/objects/items/devices/transfer_valve.dm +++ b/code/game/objects/items/devices/transfer_valve.dm @@ -1,4 +1,4 @@ -///if the icon_state for the TTV's tank is in assemblies.dmi +/// If the icon_state for the TTV's tank is in `assemblies.dmi`. #define TTV_TANK_ICON_STATES list("anesthetic", "emergency", "emergency_double", "emergency_engi", "emergency_sleep", "jetpack", "jetpack_black", "jetpack_void", "oxygen", "oxygen_f", "oxygen_fr", "plasma") /obj/item/transfer_valve @@ -14,6 +14,7 @@ var/valve_open = FALSE var/toggle = TRUE origin_tech = "materials=1;engineering=1" + new_attack_chain = TRUE /obj/item/transfer_valve/Destroy() QDEL_NULL(tank_one) @@ -23,52 +24,58 @@ return ..() /obj/item/transfer_valve/IsAssemblyHolder() - return 1 + return TRUE -/obj/item/transfer_valve/attackby__legacy__attackchain(obj/item/I, mob/user, params) - if(istype(I, /obj/item/tank)) +/obj/item/transfer_valve/item_interaction(mob/living/user, obj/item/used, list/modifiers) + if(istype(used, /obj/item/tank)) if(tank_one && tank_two) to_chat(user, SPAN_WARNING("There are already two tanks attached, remove one first.")) - return + return ITEM_INTERACT_COMPLETE if(!tank_one) - if(!user.transfer_item_to(I, src)) - return - tank_one = I + if(!user.transfer_item_to(used, src)) + return ITEM_INTERACT_COMPLETE + tank_one = used to_chat(user, SPAN_NOTICE("You attach the tank to the transfer valve.")) - if(I.w_class > w_class) - w_class = I.w_class + if(used.w_class > w_class) + w_class = used.w_class else if(!tank_two) - if(!user.transfer_item_to(I, src)) - return - tank_two = I + if(!user.transfer_item_to(used, src)) + return ITEM_INTERACT_COMPLETE + tank_two = used to_chat(user, SPAN_NOTICE("You attach the tank to the transfer valve.")) - if(I.w_class > w_class) - w_class = I.w_class + if(used.w_class > w_class) + w_class = used.w_class update_icon() - SStgui.update_uis(src) // update all UIs attached to src -//TODO: Have this take an assemblyholder - else if(isassembly(I)) - var/obj/item/assembly/A = I - if(A.secured) - to_chat(user, SPAN_NOTICE("The device is secured.")) - return - if(attached_device) - to_chat(user, SPAN_WARNING("There is already a device attached to the valve, remove it first.")) - return - if(!user.transfer_item_to(A, src)) - return - attached_device = A - to_chat(user, SPAN_NOTICE("You attach [A] to the valve controls and secure it.")) - A.holder = src - A.toggle_secure() //this calls update_icon(), which calls update_icon() on the holder (i.e. the bomb). + SStgui.update_uis(src) // Update all UIs attached to src. + return ITEM_INTERACT_COMPLETE - investigate_log("[key_name(user)] attached a [A] to a transfer valve.", INVESTIGATE_BOMB) - add_attack_logs(user, src, "attached [A] to a transfer valve", ATKLOG_FEW) - log_game("[key_name_admin(user)] attached [A] to a transfer valve.") - attacher = user - SStgui.update_uis(src) // update all UIs attached to src +//TODO: Have this take an assemblyholder + if(!isassembly(used)) + return ..() + + var/obj/item/assembly/assembly = used + if(assembly.secured) + to_chat(user, SPAN_WARNING("[assembly] is secured and cannot be attached! Loosen it with a screwdriver.")) + return ITEM_INTERACT_COMPLETE + if(attached_device) + to_chat(user, SPAN_WARNING("There is already a [attached_device.name] attached to the valve, remove it first!")) + return ITEM_INTERACT_COMPLETE + if(!user.transfer_item_to(assembly, src)) + return ITEM_INTERACT_COMPLETE + attached_device = assembly + to_chat(user, SPAN_NOTICE("You attach [assembly] to the valve controls and secure it.")) + assembly.holder = src + assembly.toggle_secure() // This calls `update_icon()`, which calls `update_icon()` on the holder (i.e. the bomb). + + investigate_log("[key_name(user)] attached a [assembly] to a transfer valve.", INVESTIGATE_BOMB) + add_attack_logs(user, src, "attached [assembly] to a transfer valve", ATKLOG_FEW) + log_game("[key_name_admin(user)] attached [assembly] to a transfer valve.") + attacher = user + SStgui.update_uis(src) // Update all UIs attached to src. + add_fingerprint(user) + return ITEM_INTERACT_COMPLETE /obj/item/transfer_valve/HasProximity(atom/movable/AM) @@ -86,8 +93,12 @@ for(var/obj/O in contents) O.hear_message(M, msg) -/obj/item/transfer_valve/attack_self__legacy__attackchain(mob/user) +/obj/item/transfer_valve/activate_self(mob/user) + if(..()) + return ITEM_INTERACT_COMPLETE ui_interact(user) + add_fingerprint(user) + return ITEM_INTERACT_COMPLETE /obj/item/transfer_valve/ui_state(mob/user) return GLOB.inventory_state @@ -106,8 +117,6 @@ data["valve"] = valve_open return data - - /obj/item/transfer_valve/ui_act(action, params) if(..()) return @@ -148,7 +157,6 @@ update_icon() add_fingerprint(usr) - /obj/item/transfer_valve/proc/process_activation(obj/item/D) if(toggle) toggle = FALSE diff --git a/code/game/objects/items/weapons/grenades/chem_grenade.dm b/code/game/objects/items/weapons/grenades/chem_grenade.dm index bec43d3e850..76f82eaeaa1 100644 --- a/code/game/objects/items/weapons/grenades/chem_grenade.dm +++ b/code/game/objects/items/weapons/grenades/chem_grenade.dm @@ -46,8 +46,6 @@ . = ..() display_timer = (stage == READY && !nadeassembly) //show/hide the timer based on assembly state - - /obj/item/grenade/chem_grenade/proc/get_trigger() if(!nadeassembly) return null for(var/obj/O in list(nadeassembly.a_left, nadeassembly.a_right)) @@ -102,7 +100,7 @@ var/turf/bombturf = get_turf(src) var/area/A = get_area(bombturf) if(nadeassembly) - nadeassembly.attack_self__legacy__attackchain(user) + nadeassembly.activate_self(user) update_icon(UPDATE_ICON_STATE) else if(clown_check(user)) // This used to go before the assembly check, but that has absolutely zero to do with priming the damn thing. You could spam the admins with it. diff --git a/code/modules/assembly/assembly.dm b/code/modules/assembly/assembly.dm index 0c305255508..45a0cddb67a 100644 --- a/code/modules/assembly/assembly.dm +++ b/code/modules/assembly/assembly.dm @@ -145,9 +145,9 @@ if(!I.use_tool(src, user, 0, volume = I.tool_volume)) return if(toggle_secure()) - to_chat(user, SPAN_NOTICE("[src] is ready!")) + to_chat(user, SPAN_NOTICE("You ready and secure [src]!")) else - to_chat(user, SPAN_NOTICE("[src] can now be attached!")) + to_chat(user, SPAN_NOTICE("You unsecure [src] with [I] so it can be attached!")) /obj/item/assembly/process() STOP_PROCESSING(SSobj, src) @@ -156,9 +156,9 @@ . = ..() if(in_range(src, user) || loc == user) if(secured) - . += "[src] is ready!" + . += "[src] is ready and secured!" else - . += "[src] can be attached!" + . += "[src] unsecured and can be attached!" /obj/item/assembly/activate_self(mob/user) if(!user) diff --git a/code/modules/assembly/assembly_holder.dm b/code/modules/assembly/assembly_holder.dm index c40b5101741..d8ea98d3b41 100644 --- a/code/modules/assembly/assembly_holder.dm +++ b/code/modules/assembly/assembly_holder.dm @@ -12,6 +12,7 @@ var/secured = FALSE var/obj/item/assembly/a_left = null var/obj/item/assembly/a_right = null + new_attack_chain = TRUE /obj/item/assembly_holder/IsAssemblyHolder() return TRUE @@ -70,9 +71,9 @@ . = ..() if(in_range(src, user) || loc == user) if(secured) - . += "[src] is ready!" + . += "[src] is ready and secured!" else - . += "[src] can be attached!" + . += "[src] is unsecured and can be attached!" /obj/item/assembly_holder/HasProximity(atom/movable/AM) @@ -148,40 +149,44 @@ a_right.toggle_secure() secured = !secured if(secured) - to_chat(user, SPAN_NOTICE("[src] is ready!")) + to_chat(user, SPAN_NOTICE("You ready and secure the [src]!")) else - to_chat(user, SPAN_NOTICE("[src] can now be taken apart!")) + to_chat(user, SPAN_NOTICE("You unsecure [src] with [I] so it can be taken apart!")) update_icon() -/obj/item/assembly_holder/attack_self__legacy__attackchain(mob/user) +/obj/item/assembly_holder/activate_self(mob/user) + if(..()) + return ITEM_INTERACT_COMPLETE add_fingerprint(user) if(secured) if(!a_left || !a_right) to_chat(user, SPAN_WARNING("Assembly part missing!")) - return + return ITEM_INTERACT_COMPLETE + if(istype(a_left, a_right.type)) // If they are the same type it causes issues due to window code switch(tgui_alert(user, "Which side would you like to use?", "Choose", list("Left", "Right"))) if("Left") a_left.activate_self(user) if("Right") a_right.activate_self(user) - return - else - a_left.activate_self(user) - a_right.activate_self(user) - else - var/turf/T = get_turf(src) - if(!T) - return FALSE - user.unequip(src, force = TRUE) - if(a_left) - a_left.on_detach() - user.put_in_active_hand(a_left) - if(a_right) // Right object is the secondary item, hence put in inactive hand - a_right.on_detach() - user.put_in_inactive_hand(a_right) - qdel(src) + return ITEM_INTERACT_COMPLETE + a_left.activate_self(user) + a_right.activate_self(user) + return ITEM_INTERACT_COMPLETE + + var/turf/T = get_turf(src) + if(!T) + return FALSE + user.unequip(src, force = TRUE) + if(a_left) + a_left.on_detach() + user.put_in_active_hand(a_left) + if(a_right) // Right object is the secondary item, hence put in inactive hand + a_right.on_detach() + user.put_in_inactive_hand(a_right) + qdel(src) + return ITEM_INTERACT_COMPLETE /obj/item/assembly_holder/proc/process_activation(obj/D, normal = TRUE, special = TRUE) if(!D) diff --git a/code/modules/assembly/bomb.dm b/code/modules/assembly/bomb.dm index 3d662583179..f44116bb12a 100644 --- a/code/modules/assembly/bomb.dm +++ b/code/modules/assembly/bomb.dm @@ -4,11 +4,12 @@ inhand_icon_state = "assembly" throwforce = 5 throw_range = 4 - flags = CONDUCT //Copied this from old code, so this may or may not be necessary - var/status = FALSE //FALSE - not readied //TRUE - bomb finished with welder - var/obj/item/assembly_holder/bombassembly = null //The first part of the bomb is an assembly holder, holding an igniter+some device - var/obj/item/tank/bombtank = null //the second part of the bomb is a plasma tank + flags = CONDUCT // Copied this from old code, so this may or may not be necessary. + var/status = FALSE // FALSE - not readied. TRUE - bomb finished with welder. + var/obj/item/assembly_holder/bombassembly = null // The first part of the bomb is an assembly holder, holding an igniter+some device. + var/obj/item/tank/bombtank = null // The second part of the bomb is a plasma tank. origin_tech = "materials=1;engineering=1" + new_attack_chain = TRUE /obj/item/onetankbomb/Initialize(mapload) . = ..() @@ -32,13 +33,14 @@ . += bombassembly.overlays . += "bomb_assembly" -/obj/item/onetankbomb/attackby__legacy__attackchain(obj/item/W, mob/user, params) - if(istype(W, /obj/item/analyzer)) - bombtank.item_interaction(user, W) - return - return ..() +/obj/item/onetankbomb/item_interaction(mob/living/user, obj/item/used, list/modifiers) + if(!istype(used, /obj/item/analyzer)) + return ..() -/obj/item/onetankbomb/wrench_act(mob/user, obj/item/I) //This is basically bomb assembly code inverted. apparently it works. + used.afterattack__legacy__attackchain(bombtank, user, TRUE, list2params(modifiers)) + return ITEM_INTERACT_COMPLETE + +/obj/item/onetankbomb/wrench_act(mob/user, obj/item/I) // This is basically bomb assembly code inverted. Apparently it works. if(status) return . = TRUE @@ -57,33 +59,37 @@ . = TRUE if(!I.use_tool(src, user, volume = I.tool_volume)) return + if(!status) status = TRUE investigate_log("[key_name(user)] welded a single tank bomb. Temperature: [bombtank.air_contents.temperature() - T0C]", INVESTIGATE_BOMB) log_game("[key_name(user)] welded a single tank bomb. Temperature: [bombtank.air_contents.temperature() - T0C]") to_chat(user, SPAN_NOTICE("A pressure hole has been bored to [bombtank] valve. [bombtank] can now be ignited.")) add_attack_logs(user, src, "welded a single tank bomb. Temperature: [bombtank.air_contents.temperature() - T0C]", ATKLOG_FEW) - else - status = FALSE - investigate_log("[key_name(user)] unwelded a single tank bomb. Temperature: [bombtank.air_contents.temperature() - T0C]", INVESTIGATE_BOMB) - add_attack_logs(user, src, "unwelded a single tank bomb. Temperature: [bombtank.air_contents.temperature() - T0C]", ATKLOG_ALMOSTALL) - to_chat(user, SPAN_NOTICE("The hole has been closed.")) + return + + status = FALSE + investigate_log("[key_name(user)] unwelded a single tank bomb. Temperature: [bombtank.air_contents.temperature() - T0C]", INVESTIGATE_BOMB) + add_attack_logs(user, src, "unwelded a single tank bomb. Temperature: [bombtank.air_contents.temperature() - T0C]", ATKLOG_ALMOSTALL) + to_chat(user, SPAN_NOTICE("The hole has been closed.")) -/obj/item/onetankbomb/attack_self__legacy__attackchain(mob/user) //pressing the bomb accesses its assembly - bombassembly.attack_self__legacy__attackchain(user, 1) +/obj/item/onetankbomb/activate_self(mob/user) // Pressing the bomb accesses its assembly. + if(..()) + return ITEM_INTERACT_COMPLETE + bombassembly.activate_self(user) add_fingerprint(user) - return + return ITEM_INTERACT_COMPLETE /obj/item/onetankbomb/HasProximity(atom/movable/AM) if(bombassembly) bombassembly.HasProximity(AM) -/obj/item/onetankbomb/proc/on_atom_entered(datum/source, atom/movable/entered) //for mousetraps +/obj/item/onetankbomb/proc/on_atom_entered(datum/source, atom/movable/entered) // For mousetraps. if(bombassembly) bombassembly.on_atom_entered(source, entered) -/obj/item/onetankbomb/on_found(mob/finder) //for mousetraps +/obj/item/onetankbomb/on_found(mob/finder) // For mousetraps. if(bombassembly) bombassembly.on_found(finder) @@ -97,31 +103,31 @@ // ---------- Procs below are for tanks that are used exclusively in 1-tank bombs ---------- -/obj/item/tank/proc/bomb_assemble(W, user) //Bomb assembly proc. This turns assembly+tank into a bomb +/obj/item/tank/proc/bomb_assemble(W, user) // Bomb assembly proc. This turns assembly+tank into a bomb. var/obj/item/assembly_holder/S = W var/mob/M = user - if(!S.secured) //Check if the assembly is secured + if(!S.secured) // Check if the assembly is secured. return - if(isigniter(S.a_left) == isigniter(S.a_right)) //Check if either part of the assembly has an igniter, but if both parts are igniters, then fuck it + if(isigniter(S.a_left) == isigniter(S.a_right)) // Check if either part of the assembly has an igniter, but if both parts are igniters, then fuck it. return var/obj/item/onetankbomb/R = new /obj/item/onetankbomb(loc) - M.drop_item() //Remove the assembly from your hands - M.unequip(src) //Remove the tank from your character,in case you were holding it - M.put_in_hands(R) //Equips the bomb if possible, or puts it on the floor. + M.drop_item() // Remove the assembly from your hands. + M.unequip(src) // Remove the tank from your character,in case you were holding it. + M.put_in_hands(R) // Equips the bomb if possible, or puts it on the floor. - R.bombassembly = S //Tell the bomb about its assembly part - S.master = R //Tell the assembly about its new owner - S.forceMove(R) //Move the assembly out of the fucking way + R.bombassembly = S // Tell the bomb about its assembly part. + S.master = R // Tell the assembly about its new owner. + S.forceMove(R) // Move the assembly out of the fucking way. - R.bombtank = src //Same for tank + R.bombtank = src // Same for tank. master = R forceMove(R) R.update_icon() return -/obj/item/tank/proc/detonate() //This happens when a bomb is told to explode +/obj/item/tank/proc/detonate() // This happens when a bomb is told to explode. var/fuel_moles = air_contents.toxins() + air_contents.oxygen() / 6 var/strength = 1 @@ -169,7 +175,7 @@ qdel(master) qdel(src) -/obj/item/tank/proc/release() //This happens when the bomb is not welded. Tank contents are just spat out. +/obj/item/tank/proc/release() // This happens when the bomb is not welded. Tank contents are just spat out. var/datum/gas_mixture/removed = air_contents.remove(air_contents.total_moles()) var/turf/simulated/T = get_turf(src) if(!T) diff --git a/code/modules/assembly/mousetrap.dm b/code/modules/assembly/mousetrap.dm index 86c1023e61a..491f4b8a518 100644 --- a/code/modules/assembly/mousetrap.dm +++ b/code/modules/assembly/mousetrap.dm @@ -88,14 +88,19 @@ which_hand = "r_hand" triggered(user, which_hand) - user.visible_message(SPAN_WARNING("[user] accidentally sets off [src], breaking [user.p_their()] fingers."), SPAN_WARNING("You accidentally trigger [src]!")) - return + user.visible_message( + SPAN_WARNING("[user] accidentally sets off [src], breaking [user.p_their()] fingers."), + SPAN_WARNING("You accidentally trigger [src]!"), + SPAN_HEAR("You hear the snap of a mousetrap and the snap of a bone!") + ) + return ITEM_INTERACT_COMPLETE to_chat(user, SPAN_NOTICE("You disarm [src].")) armed = !armed update_icon() playsound(user.loc, 'sound/weapons/handcuffs.ogg', 30, TRUE, -3) + return ITEM_INTERACT_COMPLETE /obj/item/assembly/mousetrap/attack_hand(mob/living/user) if(!armed) @@ -107,7 +112,11 @@ which_hand = "r_hand" triggered(user, which_hand) - user.visible_message(SPAN_WARNING("[user] accidentally sets off [src], breaking [user.p_their()] fingers."), SPAN_WARNING("You accidentally trigger [src]!")) + user.visible_message( + SPAN_WARNING("[user] accidentally sets off [src], breaking [user.p_their()] fingers."), + SPAN_WARNING("You accidentally trigger [src]!"), + SPAN_HEAR("You hear the snap of a mousetrap and the snap of a bone!") + ) /obj/item/assembly/mousetrap/on_atom_entered(datum/source, atom/movable/entered) @@ -116,7 +125,11 @@ var/mob/living/carbon/H = entered if(H.m_intent == MOVE_INTENT_RUN) triggered(H) - H.visible_message(SPAN_WARNING("[H] accidentally steps on [src]."), SPAN_WARNING("You accidentally step on [src]")) + H.visible_message( + SPAN_WARNING("[H] accidentally steps on [src]."), + SPAN_WARNING("You accidentally step on [src]."), + SPAN_HEAR("You hear the snap of a mousetrap.") + ) else if(ismouse(entered)) triggered(entered) @@ -128,7 +141,11 @@ /obj/item/assembly/mousetrap/on_found(mob/finder) if(armed) - finder.visible_message(SPAN_WARNING("[finder] accidentally sets off [src], breaking [finder.p_their()] fingers."), SPAN_WARNING("You accidentally trigger [src]!")) + finder.visible_message( + SPAN_WARNING("[finder] accidentally sets off [src], breaking [finder.p_their()] fingers."), + SPAN_WARNING("You accidentally trigger [src]!"), + SPAN_HEAR("You hear the snap of a mousetrap and the snap of a bone!") + ) triggered(finder, finder.hand ? "l_hand" : "r_hand") return TRUE // End the search!