Fixes circuit airlock shells being unusable (#93929)

## About The Pull Request

The shell component now listens for `COMSIG_ATOM_ITEM_INTERACTION`
instead of `COMSIG_ATOM_ATTACKBY`, allowing it to take precedence over
opening airlocks when trying to insert or modify a circuit. The wires
and maintenance panel can still be interacted with by right-clicking if
a circuit is installed.

## Why It's Good For The Game

Makes a feature actually work for the first time since it was added four
years ago.

## Changelog
🆑
fix: Integrated circuits can now correctly be inserted into
circuit-compatible airlocks.
qol: Airlock maintenance panels can now be opened/closed with right
click as well, to avoid removing an integrated circuit instead.
/🆑
This commit is contained in:
Sarah C
2025-11-15 18:29:50 +01:00
committed by GitHub
parent b0ecc87d79
commit c6dccf266b
2 changed files with 26 additions and 22 deletions
+23 -22
View File
@@ -44,7 +44,7 @@
RegisterSignal(parent, COMSIG_ATOM_ATTACK_GHOST, PROC_REF(on_attack_ghost))
if(!(shell_flags & SHELL_FLAG_CIRCUIT_UNMODIFIABLE))
RegisterSignal(parent, COMSIG_ATOM_TOOL_ACT(TOOL_MULTITOOL), PROC_REF(on_multitool_act))
RegisterSignal(parent, COMSIG_ATOM_ATTACKBY, PROC_REF(on_attack_by))
RegisterSignal(parent, COMSIG_ATOM_ITEM_INTERACTION, PROC_REF(on_item_interaction))
if(!(shell_flags & SHELL_FLAG_CIRCUIT_UNREMOVABLE))
RegisterSignal(parent, COMSIG_ATOM_TOOL_ACT(TOOL_SCREWDRIVER), PROC_REF(on_screwdriver_act))
RegisterSignal(parent, COMSIG_OBJ_DECONSTRUCT, PROC_REF(on_object_deconstruct))
@@ -91,7 +91,7 @@
/datum/component/shell/UnregisterFromParent()
UnregisterSignal(parent, list(
COMSIG_ATOM_ATTACKBY,
COMSIG_ATOM_ITEM_INTERACTION,
COMSIG_ATOM_TOOL_ACT(TOOL_SCREWDRIVER),
COMSIG_ATOM_TOOL_ACT(TOOL_MULTITOOL),
COMSIG_OBJ_DECONSTRUCT,
@@ -160,55 +160,56 @@
attached_circuit?.set_on(source.anchored)
/**
* Called when an item hits the parent. This is the method to add the circuitboard to the component.
* Called when interacting with the parent using an item. This is the method to add the circuitboard to the component.
*/
/datum/component/shell/proc/on_attack_by(atom/source, obj/item/item, mob/living/attacker)
/datum/component/shell/proc/on_item_interaction(atom/source, mob/living/user, obj/item/item, list/modifiers)
SIGNAL_HANDLER
if(!is_authorized(attacker))
if(!is_authorized(user))
return
if(istype(item, /obj/item/stock_parts/power_store/cell))
source.balloon_alert(attacker, "can't put cell in directly!")
source.balloon_alert(user, "can't put cell in directly!")
return
if(istype(item, /obj/item/inducer))
var/obj/item/inducer/inducer = item
INVOKE_ASYNC(inducer, TYPE_PROC_REF(/obj/item, interact_with_atom), attached_circuit || parent, attacker, list())
return COMPONENT_NO_AFTERATTACK
INVOKE_ASYNC(inducer, TYPE_PROC_REF(/obj/item, interact_with_atom), attached_circuit || parent, user, list())
return ITEM_INTERACT_SUCCESS
if(attached_circuit)
if(attached_circuit.owner_id && item == attached_circuit.owner_id.resolve())
set_locked(!locked)
source.balloon_alert(attacker, "[locked ? "locked" : "unlocked"] [source]")
return COMPONENT_NO_AFTERATTACK
source.balloon_alert(user, "[locked ? "locked" : "unlocked"] [source]")
return ITEM_INTERACT_SUCCESS
if(!attached_circuit.owner_id && isidcard(item))
source.balloon_alert(attacker, "owner id set for [item]")
source.balloon_alert(user, "owner id set for [item]")
attached_circuit.owner_id = WEAKREF(item)
return COMPONENT_NO_AFTERATTACK
return ITEM_INTERACT_SUCCESS
if(istype(item, /obj/item/circuit_component))
attached_circuit.add_component_manually(item, attacker)
return COMPONENT_NO_AFTERATTACK
if(attached_circuit.add_component_manually(item, user))
return ITEM_INTERACT_SUCCESS
return ITEM_INTERACT_BLOCKING
if(!istype(item, /obj/item/integrated_circuit))
return
var/obj/item/integrated_circuit/logic_board = item
. = COMPONENT_NO_AFTERATTACK
if(logic_board.shell) // I'll be surprised if this ever happens
return
return ITEM_INTERACT_BLOCKING
if(attached_circuit)
source.balloon_alert(attacker, "there is already a circuitboard inside!")
return
source.balloon_alert(user, "there is already a circuitboard inside!")
return ITEM_INTERACT_BLOCKING
if(logic_board.current_size > capacity)
source.balloon_alert(attacker, "this is too large to fit into [parent]!")
return
source.balloon_alert(user, "this is too large to fit into [parent]!")
return ITEM_INTERACT_BLOCKING
logic_board.inserter_mind = WEAKREF(attacker.mind)
attach_circuit(logic_board, attacker)
logic_board.inserter_mind = WEAKREF(user.mind)
attach_circuit(logic_board, user)
return ITEM_INTERACT_SUCCESS
/// Sets whether the shell is locked or not
/datum/component/shell/proc/set_locked(new_value)