mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-13 19:22:20 +00:00
## 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>
187 lines
7.3 KiB
Plaintext
187 lines
7.3 KiB
Plaintext
/// Teleports the movable atom back to a safe turf on the station if it leaves the z-level or becomes inaccessible.
|
|
/datum/component/stationloving
|
|
dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
|
|
/// If TRUE, notifies admins when parent is teleported back to the station.
|
|
var/inform_admins = FALSE
|
|
var/disallow_soul_imbue = TRUE
|
|
/// If FALSE, prevents parent from being qdel'd unless it's a force = TRUE qdel.
|
|
var/allow_item_destruction = FALSE
|
|
var/datum/weakref/connect_ref
|
|
|
|
/datum/component/stationloving/Initialize(inform_admins = FALSE, allow_item_destruction = FALSE)
|
|
if(!ismovable(parent))
|
|
return COMPONENT_INCOMPATIBLE
|
|
src.inform_admins = inform_admins
|
|
src.allow_item_destruction = allow_item_destruction
|
|
|
|
// Just in case something is being created outside of station/centcom
|
|
if(!atom_in_bounds(parent))
|
|
relocate()
|
|
|
|
/datum/component/stationloving/RegisterWithParent()
|
|
RegisterSignal(parent, COMSIG_PREQDELETED, PROC_REF(on_parent_pre_qdeleted))
|
|
RegisterSignal(parent, COMSIG_ITEM_IMBUE_SOUL, PROC_REF(check_soul_imbue))
|
|
RegisterSignal(parent, COMSIG_ITEM_MARK_RETRIEVAL, PROC_REF(check_mark_retrieval))
|
|
// Relocate when we become unreachable
|
|
RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(on_parent_moved))
|
|
// Relocate when our loc, or any of our loc's locs, becomes unreachable
|
|
var/static/list/loc_connections = list(
|
|
COMSIG_MOVABLE_MOVED = PROC_REF(on_parent_moved),
|
|
SIGNAL_ADDTRAIT(TRAIT_SECLUDED_LOCATION) = PROC_REF(on_loc_secluded),
|
|
)
|
|
connect_ref = WEAKREF(AddComponent(/datum/component/connect_containers, parent, loc_connections))
|
|
|
|
/datum/component/stationloving/UnregisterFromParent()
|
|
UnregisterSignal(parent, list(
|
|
COMSIG_MOVABLE_Z_CHANGED,
|
|
COMSIG_PREQDELETED,
|
|
COMSIG_ITEM_IMBUE_SOUL,
|
|
COMSIG_ITEM_MARK_RETRIEVAL,
|
|
COMSIG_MOVABLE_MOVED,
|
|
))
|
|
|
|
qdel(connect_ref)
|
|
|
|
/datum/component/stationloving/InheritComponent(datum/component/stationloving/newc, original, inform_admins, allow_death)
|
|
if (original)
|
|
if (newc)
|
|
inform_admins = newc.inform_admins
|
|
allow_death = newc.allow_item_destruction
|
|
else
|
|
inform_admins = inform_admins
|
|
|
|
/// Teleports parent to a safe turf on the station z-level.
|
|
/datum/component/stationloving/proc/relocate()
|
|
|
|
var/target_turf = length(GLOB.the_station_areas) ? get_safe_random_station_turf(GLOB.the_station_areas) : find_safe_turf() //Fallback. Mostly for debug maps.
|
|
|
|
if(!target_turf)
|
|
if(GLOB.blobstart.len > 0)
|
|
target_turf = get_turf(pick(GLOB.blobstart))
|
|
else
|
|
CRASH("Unable to find a blobstart landmark for [type] to relocate [parent].")
|
|
|
|
var/atom/movable/movable_parent = parent
|
|
playsound(movable_parent, 'sound/machines/synth/synth_no.ogg', 5, TRUE)
|
|
|
|
var/mob/holder = get(movable_parent, /mob)
|
|
if(holder)
|
|
to_chat(holder, span_danger("You can't help but feel that you just lost something back there..."))
|
|
holder.temporarilyRemoveItemFromInventory(parent, TRUE) // prevents ghost diskie
|
|
|
|
movable_parent.forceMove(target_turf)
|
|
|
|
return target_turf
|
|
|
|
/// Signal proc for [COMSIG_MOVABLE_MOVED], called when our parent moves, or our parent's loc, or our parent's loc loc...
|
|
/// To check if our disk is moving somewhere it shouldn't be, such as off Z level, or into an invalid area
|
|
/datum/component/stationloving/proc/on_parent_moved(atom/movable/source, turf/old_turf)
|
|
SIGNAL_HANDLER
|
|
|
|
if(atom_in_bounds(source))
|
|
return
|
|
|
|
var/turf/current_turf = get_turf(source)
|
|
var/turf/new_destination = relocate()
|
|
// Our turf actually didn't change, so it's more likely we became secluded
|
|
if(current_turf == old_turf)
|
|
log_game("[parent] moved out of bounds at [loc_name(current_turf)], becoming inaccessible / secluded. \
|
|
Moving it to [loc_name(new_destination)].")
|
|
|
|
if(inform_admins)
|
|
message_admins("[parent] moved out of bounds at [ADMIN_VERBOSEJMP(current_turf)], becoming inaccessible / secluded. \
|
|
Moving it to [ADMIN_VERBOSEJMP(new_destination)].")
|
|
|
|
// Our locs changes, we did in fact move somewhere
|
|
else
|
|
log_game("[parent] attempted to be moved out of bounds from [loc_name(old_turf)] \
|
|
to [loc_name(current_turf)]. Moving it to [loc_name(new_destination)].")
|
|
|
|
if(inform_admins)
|
|
message_admins("[parent] attempted to be moved out of bounds from [ADMIN_VERBOSEJMP(old_turf)] \
|
|
to [ADMIN_VERBOSEJMP(current_turf)]. Moving it to [ADMIN_VERBOSEJMP(new_destination)].")
|
|
|
|
/// Signal proc for [SIGNAL_ADDTRAIT], via [TRAIT_SECLUDED_LOCATION] on our locs, to ensure nothing funky happens
|
|
/datum/component/stationloving/proc/on_loc_secluded(atom/movable/source)
|
|
SIGNAL_HANDLER
|
|
|
|
var/turf/new_destination = relocate()
|
|
log_game("[parent] moved out of bounds at [loc_name(source)], becoming inaccessible / secluded. \
|
|
Moving it to [loc_name(new_destination)].")
|
|
|
|
if(inform_admins)
|
|
message_admins("[parent] moved out of bounds at [ADMIN_VERBOSEJMP(source)], becoming inaccessible / secluded. \
|
|
Moving it to [ADMIN_VERBOSEJMP(new_destination)].")
|
|
|
|
/datum/component/stationloving/proc/check_soul_imbue(datum/source)
|
|
SIGNAL_HANDLER
|
|
|
|
if(disallow_soul_imbue)
|
|
return COMPONENT_BLOCK_IMBUE
|
|
|
|
/datum/component/stationloving/proc/check_mark_retrieval(datum/source)
|
|
SIGNAL_HANDLER
|
|
|
|
return COMPONENT_BLOCK_MARK_RETRIEVAL
|
|
|
|
/// Checks whether a given atom's turf is within bounds. Returns TRUE if it is, FALSE if it isn't.
|
|
/datum/component/stationloving/proc/atom_in_bounds(atom/atom_to_check)
|
|
// Typecache of shuttles that we allow the disk to stay on
|
|
var/static/list/allowed_shuttles = typecacheof(list(
|
|
/area/shuttle/syndicate,
|
|
/area/shuttle/escape,
|
|
/area/shuttle/pod_1,
|
|
/area/shuttle/pod_2,
|
|
/area/shuttle/pod_3,
|
|
/area/shuttle/pod_4,
|
|
))
|
|
// Typecache of areas on the centcom Z-level that we allow the disk to stay on
|
|
var/static/list/disallowed_centcom_areas = typecacheof(list(
|
|
/area/centcom/abductor_ship,
|
|
/area/awaymission/errorroom,
|
|
))
|
|
|
|
// Our loc is a secluded location = not in bounds
|
|
if (atom_to_check.loc && HAS_TRAIT(atom_to_check.loc, TRAIT_SECLUDED_LOCATION))
|
|
return FALSE
|
|
// No turf below us = nullspace = not in bounds
|
|
var/turf/destination_turf = get_turf(atom_to_check)
|
|
if (!destination_turf)
|
|
return FALSE
|
|
if (is_station_level(destination_turf.z))
|
|
return TRUE
|
|
if(atom_to_check.onSyndieBase())
|
|
return TRUE
|
|
|
|
var/area/destination_area = destination_turf.loc
|
|
if (is_centcom_level(destination_turf.z))
|
|
if (is_type_in_typecache(destination_area, disallowed_centcom_areas))
|
|
return FALSE
|
|
return TRUE
|
|
if (is_reserved_level(destination_turf.z))
|
|
if (is_type_in_typecache(destination_area, allowed_shuttles))
|
|
return TRUE
|
|
|
|
return FALSE
|
|
|
|
/// Signal handler for before the parent is qdel'd. Can prevent the parent from being deleted where allow_item_destruction is FALSE and force is FALSE.
|
|
/datum/component/stationloving/proc/on_parent_pre_qdeleted(datum/source, force)
|
|
SIGNAL_HANDLER
|
|
|
|
var/turf/current_turf = get_turf(parent)
|
|
|
|
if(force && inform_admins)
|
|
message_admins("[parent] has been !!force deleted!! in [ADMIN_VERBOSEJMP(current_turf)].")
|
|
log_game("[parent] has been !!force deleted!! in [loc_name(current_turf)].")
|
|
|
|
if(force || allow_item_destruction)
|
|
return FALSE
|
|
|
|
var/turf/new_turf = relocate()
|
|
log_game("[parent] has been destroyed in [loc_name(current_turf)]. \
|
|
Preventing destruction and moving it to [loc_name(new_turf)].")
|
|
if(inform_admins)
|
|
message_admins("[parent] has been destroyed in [ADMIN_VERBOSEJMP(current_turf)]. \
|
|
Preventing destruction and moving it to [ADMIN_VERBOSEJMP(new_turf)].")
|
|
return TRUE
|