Files
Bubberstation/code/datums/components/connect_containers.dm
Y0SH1M4S73R f8511ea227 You can install B.O.R.I.S. in circuits with MMI components (+other MMI component changes) (#92002)
## About The Pull Request

This PR adds the ability to install a B.O.R.I.S. in a circuit that
contains an MMI component. These circuits can then be remotely connected
to by an AI by clicking on them or anything they are inside of. To
indicate that a circuit allows remote AI connection, an indicator is
given to the circuit and anything containing it.

Additionally:
- Refactors the MMI component to use `item_interaction`, since it was
pertinent.
- You cannot insert an MMI/B.O.R.I.S. into a locked circuit.
- You can no longer hotswap MMIs/B.O.R.I.S.es - you must manually eject
the inserted one.

Let me know what changelog labels I should use for the hotswap removal
and the prevention of insertion into locked circuits.

## Why It's Good For The Game

If you can put an MMI or posibrain in a circuit, why not allow an AI to
use it using a B.O.R.I.S.?

## Changelog

🆑
add: B.O.R.I.S.es can be installed inside of integrated circuits with
MMI components, allowing an AI to remotely interface with them the same
way an MMI or posibrain could.
refactor: The MMI component now uses item interaction behavior for
inserting MMIs/B.O.R.I.S.es.
/🆑

---------

Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com>
2025-09-03 23:25:50 -07:00

69 lines
2.5 KiB
Plaintext

/// This component behaves similar to connect_loc_behalf, but it's nested and hooks a signal onto all MOVABLES containing this atom.
/datum/component/connect_containers
dupe_mode = COMPONENT_DUPE_SELECTIVE
/// An assoc list of signal -> procpath to register to the loc this object is on.
var/list/connections
/**
* The atom the component is tracking. The component will delete itself if the tracked is deleted.
* Signals will also be updated whenever it moves.
*/
var/atom/movable/tracked
/datum/component/connect_containers/Initialize(atom/movable/tracked, list/connections)
. = ..()
if (!ismovable(tracked))
return COMPONENT_INCOMPATIBLE
src.connections = connections
set_tracked(tracked)
/datum/component/connect_containers/Destroy()
set_tracked(null)
return ..()
/datum/component/connect_containers/CheckDupeComponent(datum/component/connect_containers/new_component, atom/movable/tracked, list/connections)
// Not equivalent. Checks if they are not the same list via shallow comparison.
if(!compare_list(src.connections, connections))
return FALSE // Different set of connections.
if(src.tracked != tracked)
set_tracked(tracked) // Different target for the same set of connections, track the new target.
return TRUE // No new component.
/datum/component/connect_containers/proc/set_tracked(atom/movable/new_tracked)
if(tracked)
UnregisterSignal(tracked, list(COMSIG_MOVABLE_MOVED, COMSIG_QDELETING))
unregister_signals(tracked)
tracked = new_tracked
if(!tracked)
return
RegisterSignal(tracked, COMSIG_MOVABLE_MOVED, PROC_REF(on_moved))
RegisterSignal(tracked, COMSIG_QDELETING, PROC_REF(handle_tracked_qdel))
update_signals(tracked)
/datum/component/connect_containers/proc/handle_tracked_qdel()
SIGNAL_HANDLER
qdel(src)
/datum/component/connect_containers/proc/update_signals(atom/movable/listener)
if(!ismovable(listener.loc))
return
for(var/atom/movable/container as anything in get_nested_locs(listener))
RegisterSignal(container, COMSIG_MOVABLE_MOVED, PROC_REF(on_moved))
for(var/signal in connections)
parent.RegisterSignal(container, signal, connections[signal])
/datum/component/connect_containers/proc/unregister_signals(atom/movable/location)
if(!ismovable(location))
return
for(var/atom/movable/target as anything in (get_nested_locs(location) + location))
UnregisterSignal(target, COMSIG_MOVABLE_MOVED)
parent.UnregisterSignal(target, connections)
/datum/component/connect_containers/proc/on_moved(atom/movable/listener, atom/old_loc)
SIGNAL_HANDLER
unregister_signals(old_loc)
update_signals(listener)