mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-11 10:11:09 +00:00
* Adds USB to arrest consoles. Adds list circuit components. (#59850) Co-authored-by: Watermelon914 <3052169-Watermelon914@ users.noreply.gitlab.com> Co-authored-by: Mothblocks <35135081+Mothblocks@ users.noreply.github.com> * Adds USB to arrest consoles. Adds list circuit components. Co-authored-by: Watermelon914 <37270891+Watermelon914@users.noreply.github.com> Co-authored-by: Watermelon914 <3052169-Watermelon914@ users.noreply.gitlab.com> Co-authored-by: Mothblocks <35135081+Mothblocks@ users.noreply.github.com>
242 lines
8.5 KiB
Plaintext
242 lines
8.5 KiB
Plaintext
/// Makes an atom a shell that is able to take in an attached circuit.
|
|
/datum/component/shell
|
|
dupe_mode = COMPONENT_DUPE_UNIQUE
|
|
|
|
/// The circuitboard attached to this shell
|
|
var/obj/item/integrated_circuit/attached_circuit
|
|
|
|
/// Flags containing what this shell can do
|
|
var/shell_flags = NONE
|
|
|
|
/// The capacity of the shell.
|
|
var/capacity = INFINITY
|
|
|
|
/// A list of components that cannot be removed
|
|
var/list/obj/item/circuit_component/unremovable_circuit_components
|
|
|
|
var/locked = FALSE
|
|
|
|
/datum/component/shell/Initialize(unremovable_circuit_components, capacity, shell_flags)
|
|
. = ..()
|
|
if(!ismovable(parent))
|
|
return COMPONENT_INCOMPATIBLE
|
|
|
|
src.shell_flags = shell_flags || src.shell_flags
|
|
src.capacity = capacity || src.capacity
|
|
src.unremovable_circuit_components = unremovable_circuit_components
|
|
|
|
for(var/obj/item/circuit_component/circuit_component as anything in unremovable_circuit_components)
|
|
circuit_component.removable = FALSE
|
|
|
|
/datum/component/shell/RegisterWithParent()
|
|
RegisterSignal(parent, COMSIG_PARENT_ATTACKBY, .proc/on_attack_by)
|
|
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/on_examine)
|
|
RegisterSignal(parent, COMSIG_ATOM_ATTACK_GHOST, .proc/on_attack_ghost)
|
|
if(!(shell_flags & SHELL_FLAG_CIRCUIT_FIXED))
|
|
RegisterSignal(parent, COMSIG_ATOM_TOOL_ACT(TOOL_SCREWDRIVER), .proc/on_screwdriver_act)
|
|
RegisterSignal(parent, COMSIG_ATOM_TOOL_ACT(TOOL_MULTITOOL), .proc/on_multitool_act)
|
|
RegisterSignal(parent, COMSIG_OBJ_DECONSTRUCT, .proc/on_object_deconstruct)
|
|
if(shell_flags & SHELL_FLAG_REQUIRE_ANCHOR)
|
|
RegisterSignal(parent, COMSIG_OBJ_DEFAULT_UNFASTEN_WRENCH, .proc/on_unfasten)
|
|
RegisterSignal(parent, COMSIG_ATOM_USB_CABLE_TRY_ATTACH, .proc/on_atom_usb_cable_try_attach)
|
|
|
|
|
|
/datum/component/shell/UnregisterFromParent()
|
|
UnregisterSignal(parent, list(
|
|
COMSIG_PARENT_ATTACKBY,
|
|
COMSIG_ATOM_TOOL_ACT(TOOL_SCREWDRIVER),
|
|
COMSIG_ATOM_TOOL_ACT(TOOL_MULTITOOL),
|
|
COMSIG_OBJ_DECONSTRUCT,
|
|
COMSIG_OBJ_DEFAULT_UNFASTEN_WRENCH,
|
|
COMSIG_PARENT_EXAMINE,
|
|
COMSIG_ATOM_ATTACK_GHOST,
|
|
COMSIG_ATOM_USB_CABLE_TRY_ATTACH,
|
|
))
|
|
|
|
QDEL_NULL(attached_circuit)
|
|
|
|
/datum/component/shell/Destroy(force, silent)
|
|
QDEL_LIST(unremovable_circuit_components)
|
|
return ..()
|
|
|
|
/datum/component/shell/proc/on_object_deconstruct()
|
|
SIGNAL_HANDLER
|
|
remove_circuit()
|
|
|
|
/datum/component/shell/proc/on_attack_ghost(datum/source, mob/dead/observer/ghost)
|
|
SIGNAL_HANDLER
|
|
if(attached_circuit)
|
|
INVOKE_ASYNC(attached_circuit, /datum.proc/ui_interact, ghost)
|
|
|
|
/datum/component/shell/proc/on_examine(datum/source, mob/user, list/examine_text)
|
|
SIGNAL_HANDLER
|
|
if(!attached_circuit)
|
|
examine_text += span_notice("There is no integrated circuit attached.")
|
|
return
|
|
|
|
examine_text += span_notice("There is an integrated circuit attached. Use a multitool to access the wiring. Use a screwdriver to remove it from [source].")
|
|
examine_text += span_notice("The cover panel to the integrated circuit is [locked? "locked" : "unlocked"].")
|
|
var/obj/item/stock_parts/cell/cell = attached_circuit.cell
|
|
examine_text += span_notice("The charge meter reads [cell ? round(cell.percent(), 1) : 0]%.")
|
|
|
|
if (shell_flags & SHELL_FLAG_USB_PORT)
|
|
examine_text += span_notice("There is a <b>USB port</b> on the front.")
|
|
|
|
/**
|
|
* Called when the shell is wrenched.
|
|
*
|
|
* Only applies if the shell has SHELL_FLAG_REQUIRE_ANCHOR.
|
|
* Disables the integrated circuit if unanchored, otherwise enable the circuit.
|
|
*/
|
|
/datum/component/shell/proc/on_unfasten(atom/source, anchored)
|
|
SIGNAL_HANDLER
|
|
attached_circuit?.on = anchored
|
|
/**
|
|
* Called when an item hits the parent. 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)
|
|
SIGNAL_HANDLER
|
|
if(istype(item, /obj/item/stock_parts/cell))
|
|
source.balloon_alert(attacker, "can't pull cell in directly!")
|
|
return
|
|
|
|
if(attached_circuit?.owner_id && item == attached_circuit.owner_id.resolve())
|
|
locked = !locked
|
|
source.balloon_alert(attacker, "[locked? "locked" : "unlocked"] [source]")
|
|
return COMPONENT_NO_AFTERATTACK
|
|
|
|
if(attached_circuit && istype(item, /obj/item/circuit_component))
|
|
attached_circuit.add_component(item, attacker)
|
|
return
|
|
|
|
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
|
|
|
|
if(attached_circuit)
|
|
source.balloon_alert(attacker, "there is already a circuitboard inside!")
|
|
return
|
|
|
|
if(length(logic_board.attached_components) > capacity)
|
|
source.balloon_alert(attacker, "this is too large to fit into [parent]!")
|
|
return
|
|
|
|
logic_board.inserter_mind = WEAKREF(attacker.mind)
|
|
attach_circuit(logic_board, attacker)
|
|
|
|
/datum/component/shell/proc/on_multitool_act(atom/source, mob/user, obj/item/tool)
|
|
SIGNAL_HANDLER
|
|
if(!attached_circuit)
|
|
return
|
|
|
|
if(locked)
|
|
if(shell_flags & SHELL_FLAG_ALLOW_FAILURE_ACTION)
|
|
return
|
|
source.balloon_alert(user, "it's locked!")
|
|
return COMPONENT_BLOCK_TOOL_ATTACK
|
|
|
|
attached_circuit.interact(user)
|
|
return COMPONENT_BLOCK_TOOL_ATTACK
|
|
|
|
/**
|
|
* Called when a screwdriver is used on the parent. Removes the circuitboard from the component.
|
|
*/
|
|
/datum/component/shell/proc/on_screwdriver_act(atom/source, mob/user, obj/item/tool)
|
|
SIGNAL_HANDLER
|
|
if(!attached_circuit)
|
|
return
|
|
|
|
if(locked)
|
|
if(shell_flags & SHELL_FLAG_ALLOW_FAILURE_ACTION)
|
|
return
|
|
source.balloon_alert(user, "it's locked!")
|
|
return COMPONENT_BLOCK_TOOL_ATTACK
|
|
|
|
tool.play_tool_sound(parent)
|
|
source.balloon_alert(user, "you unscrew [attached_circuit] from [parent].")
|
|
remove_circuit()
|
|
return COMPONENT_BLOCK_TOOL_ATTACK
|
|
|
|
/**
|
|
* Checks for when the circuitboard moves. If it moves, removes it from the component.
|
|
*/
|
|
/datum/component/shell/proc/on_circuit_moved(obj/item/integrated_circuit/circuit, atom/new_loc)
|
|
SIGNAL_HANDLER
|
|
if(new_loc != parent)
|
|
remove_circuit()
|
|
|
|
/**
|
|
* Checks for when the circuitboard deletes so that it can be unassigned.
|
|
*/
|
|
/datum/component/shell/proc/on_circuit_delete(datum/source)
|
|
SIGNAL_HANDLER
|
|
remove_circuit()
|
|
|
|
/datum/component/shell/proc/on_circuit_add_component_manually(atom/source, obj/item/circuit_component/added_comp, mob/living/user)
|
|
SIGNAL_HANDLER
|
|
if(locked)
|
|
source.balloon_alert(user, "it's locked!")
|
|
return COMPONENT_CANCEL_ADD_COMPONENT
|
|
|
|
if(length(attached_circuit.attached_components) - length(unremovable_circuit_components) >= capacity)
|
|
source.balloon_alert(user, "it's at maximum capacity!")
|
|
return COMPONENT_CANCEL_ADD_COMPONENT
|
|
|
|
/**
|
|
* Attaches a circuit to the parent. Doesn't do any checks to see for any existing circuits so that should be done beforehand.
|
|
*/
|
|
/datum/component/shell/proc/attach_circuit(obj/item/integrated_circuit/circuitboard, mob/living/user)
|
|
if(!user.transferItemToLoc(circuitboard, parent))
|
|
return
|
|
locked = FALSE
|
|
attached_circuit = circuitboard
|
|
RegisterSignal(circuitboard, COMSIG_MOVABLE_MOVED, .proc/on_circuit_moved)
|
|
RegisterSignal(circuitboard, COMSIG_PARENT_QDELETING, .proc/on_circuit_delete)
|
|
for(var/obj/item/circuit_component/to_add as anything in unremovable_circuit_components)
|
|
to_add.forceMove(attached_circuit)
|
|
attached_circuit.add_component(to_add)
|
|
RegisterSignal(circuitboard, COMSIG_CIRCUIT_ADD_COMPONENT_MANUALLY, .proc/on_circuit_add_component_manually)
|
|
attached_circuit.set_shell(parent)
|
|
|
|
if(shell_flags & SHELL_FLAG_REQUIRE_ANCHOR)
|
|
var/atom/movable/parent_atom = parent
|
|
on_unfasten(parent_atom, parent_atom.anchored)
|
|
|
|
/**
|
|
* Removes the circuit from the component. Doesn't do any checks to see for an existing circuit so that should be done beforehand.
|
|
*/
|
|
/datum/component/shell/proc/remove_circuit()
|
|
attached_circuit.on = TRUE
|
|
attached_circuit.remove_current_shell()
|
|
UnregisterSignal(attached_circuit, list(
|
|
COMSIG_MOVABLE_MOVED,
|
|
COMSIG_PARENT_QDELETING,
|
|
COMSIG_CIRCUIT_ADD_COMPONENT_MANUALLY,
|
|
))
|
|
if(attached_circuit.loc == parent)
|
|
var/atom/parent_atom = parent
|
|
attached_circuit.forceMove(parent_atom.drop_location())
|
|
|
|
for(var/obj/item/circuit_component/to_remove as anything in unremovable_circuit_components)
|
|
attached_circuit.remove_component(to_remove)
|
|
to_remove.moveToNullspace()
|
|
attached_circuit = null
|
|
|
|
/datum/component/shell/proc/on_atom_usb_cable_try_attach(atom/source, obj/item/usb_cable/usb_cable, mob/user)
|
|
SIGNAL_HANDLER
|
|
|
|
if (!(shell_flags & SHELL_FLAG_USB_PORT))
|
|
source.balloon_alert(user, "this shell has no usb ports")
|
|
return COMSIG_CANCEL_USB_CABLE_ATTACK
|
|
|
|
if (isnull(attached_circuit))
|
|
source.balloon_alert(user, "no circuit inside")
|
|
return COMSIG_CANCEL_USB_CABLE_ATTACK
|
|
|
|
usb_cable.attached_circuit = attached_circuit
|
|
return COMSIG_USB_CABLE_CONNECTED_TO_CIRCUIT
|