mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-10 17:52:36 +00:00
## About The Pull Request This PR introduces a limited set of camera components that can be used by surveillance security consoles and the PDA/laptop camera app. <img width="366" alt="components" src="https://github.com/tgstation/tgstation/assets/80724828/0e628863-9998-46d6-8822-e0a44543b4c2"> There is four camera components, each limited to a specified shell circuit type. Additionally, drone circuit shells can now use the recharge stations too, much like how mobs with BCIs can recharge. ### New Components <img width="136" alt="drone camera" src="https://github.com/tgstation/tgstation/assets/80724828/fd045871-56bf-44a6-bb4f-ebe895d56d3d"> * Drone Camera This camera component captures the surrounding area. It has an option to set the camera range (near 5x5/far 14x14). <img width="136" alt="bci camera" src="https://github.com/tgstation/tgstation/assets/80724828/16bf2dd1-823b-4d66-8249-5d0f1bb1b779"> * BCI Camera This camera component uses the active user's eyes as a camera function. If the user's sights are damaged, the range will be forced to the near setting. If the user is unconscious/dead/blinded or has no eyes, the stream will be cut off. It has an option to set the camera range (near 5x5/far 14x14). <img width="136" alt="polaroid camera" src="https://github.com/tgstation/tgstation/assets/80724828/7c4d53df-b4af-4f7c-8942-a63842510720"> * Polaroid Camera Add-On This camera component streams to a camera network. The camera range is hardcoded to the near setting (5x5). <img width="136" alt="airlock camera" src="https://github.com/tgstation/tgstation/assets/80724828/5d9e9d55-49fc-45a7-99c8-aaf1ae08f6d1"> * Airlock Camera This camera component streams to a camera network. The camera range is hardcoded to the near setting (5x5). ### Features * The cameras can be EMP'd and will be disabled for 90 seconds if successful * When the cameras are active, they will actively drain the cell's power per second (near range uses 3kJ & far range uses 8kJ) * Advance camera console/AIs can use these cameras, however the camera light is disabled (they will be useless in dark areas) ### Screenshots In Action <details> This is the drone camera viewed on a security camera console<br> <img width="425" alt="near" src="https://github.com/tgstation/tgstation/assets/80724828/e5247828-0fee-4552-9e70-5e5ee897c117"><br> This is the same drone, now set to the far range setting<br> <img width="425" alt="far" src="https://github.com/tgstation/tgstation/assets/80724828/e58e3e85-aa90-4f1a-9dff-957c65764b77"><br> </details> ## Why It's Good For The Game This promotes emergent gameplay and improves the overall usefulness for drones as they can be 100% used remotely. ## Changelog 🆑 add: Added new circuit camera components qol: Circuit drones can now recharge at recharge stations /🆑 --------- Co-authored-by: Watermelon914 <37270891+Watermelon914@users.noreply.github.com>
203 lines
6.6 KiB
Plaintext
203 lines
6.6 KiB
Plaintext
/datum/wires/airlock/shell
|
|
holder_type = /obj/machinery/door/airlock/shell
|
|
proper_name = "Circuit Airlock"
|
|
|
|
/datum/wires/airlock/shell/on_cut(wire, mend, source)
|
|
// Don't allow them to re-enable autoclose.
|
|
if(wire == WIRE_TIMING)
|
|
return
|
|
return ..()
|
|
|
|
/obj/machinery/door/airlock/shell
|
|
name = "circuit airlock"
|
|
autoclose = FALSE
|
|
|
|
/obj/machinery/door/airlock/shell/Initialize(mapload)
|
|
. = ..()
|
|
AddComponent( \
|
|
/datum/component/shell, \
|
|
unremovable_circuit_components = list(new /obj/item/circuit_component/airlock, new /obj/item/circuit_component/airlock_access_event, new /obj/item/circuit_component/remotecam/airlock), \
|
|
capacity = SHELL_CAPACITY_LARGE, \
|
|
shell_flags = SHELL_FLAG_ALLOW_FAILURE_ACTION|SHELL_FLAG_REQUIRE_ANCHOR \
|
|
)
|
|
|
|
/obj/machinery/door/airlock/shell/check_access(obj/item/I)
|
|
return FALSE
|
|
|
|
/obj/machinery/door/airlock/shell/canAIControl(mob/user)
|
|
return FALSE
|
|
|
|
/obj/machinery/door/airlock/shell/canAIHack(mob/user)
|
|
return FALSE
|
|
|
|
/obj/machinery/door/airlock/shell/allowed(mob/user)
|
|
if(SEND_SIGNAL(src, COMSIG_AIRLOCK_SHELL_ALLOWED, user) & COMPONENT_OBJ_ALLOW)
|
|
return TRUE
|
|
return isAdminGhostAI(user)
|
|
|
|
/obj/machinery/door/airlock/shell/get_wires()
|
|
return new /datum/wires/airlock/shell(src)
|
|
|
|
/obj/item/circuit_component/airlock
|
|
display_name = "Airlock"
|
|
desc = "The general interface with an airlock. Includes general statuses of the airlock"
|
|
|
|
/// The shell, if it is an airlock.
|
|
var/obj/machinery/door/airlock/attached_airlock
|
|
|
|
/// Bolts the airlock (if possible)
|
|
var/datum/port/input/bolt
|
|
/// Unbolts the airlock (if possible)
|
|
var/datum/port/input/unbolt
|
|
/// Opens the airlock (if possible)
|
|
var/datum/port/input/open
|
|
/// Closes the airlock (if possible)
|
|
var/datum/port/input/close
|
|
|
|
/// Contains whether the airlock is open or not
|
|
var/datum/port/output/is_open
|
|
/// Contains whether the airlock is bolted or not
|
|
var/datum/port/output/is_bolted
|
|
|
|
/// Called when the airlock is opened.
|
|
var/datum/port/output/opened
|
|
/// Called when the airlock is closed
|
|
var/datum/port/output/closed
|
|
|
|
/// Called when the airlock is bolted
|
|
var/datum/port/output/bolted
|
|
/// Called when the airlock is unbolted
|
|
var/datum/port/output/unbolted
|
|
|
|
/obj/item/circuit_component/airlock/populate_ports()
|
|
// Input Signals
|
|
bolt = add_input_port("Bolt", PORT_TYPE_SIGNAL)
|
|
unbolt = add_input_port("Unbolt", PORT_TYPE_SIGNAL)
|
|
open = add_input_port("Open", PORT_TYPE_SIGNAL)
|
|
close = add_input_port("Close", PORT_TYPE_SIGNAL)
|
|
// States
|
|
is_open = add_output_port("Is Open", PORT_TYPE_NUMBER)
|
|
is_bolted = add_output_port("Is Bolted", PORT_TYPE_NUMBER)
|
|
// Output Signals
|
|
opened = add_output_port("Opened", PORT_TYPE_SIGNAL)
|
|
closed = add_output_port("Closed", PORT_TYPE_SIGNAL)
|
|
bolted = add_output_port("Bolted", PORT_TYPE_SIGNAL)
|
|
unbolted = add_output_port("Unbolted", PORT_TYPE_SIGNAL)
|
|
|
|
/obj/item/circuit_component/airlock/register_shell(atom/movable/shell)
|
|
. = ..()
|
|
if(istype(shell, /obj/machinery/door/airlock))
|
|
attached_airlock = shell
|
|
RegisterSignal(shell, COMSIG_AIRLOCK_SET_BOLT, PROC_REF(on_airlock_set_bolted))
|
|
RegisterSignal(shell, COMSIG_AIRLOCK_OPEN, PROC_REF(on_airlock_open))
|
|
RegisterSignal(shell, COMSIG_AIRLOCK_CLOSE, PROC_REF(on_airlock_closed))
|
|
|
|
/obj/item/circuit_component/airlock/unregister_shell(atom/movable/shell)
|
|
attached_airlock = null
|
|
UnregisterSignal(shell, list(
|
|
COMSIG_AIRLOCK_SET_BOLT,
|
|
COMSIG_AIRLOCK_OPEN,
|
|
COMSIG_AIRLOCK_CLOSE,
|
|
))
|
|
return ..()
|
|
|
|
/obj/item/circuit_component/airlock/proc/on_airlock_set_bolted(datum/source, should_bolt)
|
|
SIGNAL_HANDLER
|
|
is_bolted.set_output(should_bolt)
|
|
if(should_bolt)
|
|
bolted.set_output(COMPONENT_SIGNAL)
|
|
else
|
|
unbolted.set_output(COMPONENT_SIGNAL)
|
|
|
|
/obj/item/circuit_component/airlock/proc/on_airlock_open(datum/source, force)
|
|
SIGNAL_HANDLER
|
|
is_open.set_output(TRUE)
|
|
opened.set_output(COMPONENT_SIGNAL)
|
|
|
|
/obj/item/circuit_component/airlock/proc/on_airlock_closed(datum/source, forced)
|
|
SIGNAL_HANDLER
|
|
is_open.set_output(FALSE)
|
|
closed.set_output(COMPONENT_SIGNAL)
|
|
|
|
/obj/item/circuit_component/airlock/input_received(datum/port/input/port)
|
|
|
|
if(!attached_airlock)
|
|
return
|
|
|
|
if(COMPONENT_TRIGGERED_BY(bolt, port))
|
|
attached_airlock.bolt()
|
|
if(COMPONENT_TRIGGERED_BY(unbolt, port))
|
|
attached_airlock.unbolt()
|
|
if(COMPONENT_TRIGGERED_BY(open, port) && attached_airlock.density)
|
|
INVOKE_ASYNC(attached_airlock, TYPE_PROC_REF(/obj/machinery/door/airlock, open))
|
|
if(COMPONENT_TRIGGERED_BY(close, port) && !attached_airlock.density)
|
|
INVOKE_ASYNC(attached_airlock, TYPE_PROC_REF(/obj/machinery/door/airlock, close))
|
|
|
|
|
|
/obj/item/circuit_component/airlock_access_event
|
|
display_name = "Airlock Access Event"
|
|
desc = "An event that can be handled through circuit components to determine if the door should open or not for an entity that might be trying to access it."
|
|
circuit_flags = CIRCUIT_FLAG_INSTANT
|
|
|
|
/// The shell, if it is an airlock.
|
|
var/obj/machinery/door/airlock/attached_airlock
|
|
|
|
/// Tells the event to open the airlock.
|
|
var/datum/port/input/open_airlock
|
|
|
|
/// The person trying to open the airlock.
|
|
var/datum/port/output/accessing_entity
|
|
|
|
/// The signal sent when this event is triggered
|
|
var/datum/port/output/event_triggered
|
|
|
|
|
|
/obj/item/circuit_component/airlock_access_event/register_shell(atom/movable/shell)
|
|
. = ..()
|
|
if(istype(shell, /obj/machinery/door/airlock))
|
|
attached_airlock = shell
|
|
RegisterSignals(shell, list(
|
|
COMSIG_OBJ_ALLOWED,
|
|
COMSIG_AIRLOCK_SHELL_ALLOWED,
|
|
), PROC_REF(handle_allowed))
|
|
|
|
/obj/item/circuit_component/airlock_access_event/unregister_shell(atom/movable/shell)
|
|
attached_airlock = null
|
|
UnregisterSignal(shell, list(
|
|
COMSIG_OBJ_ALLOWED,
|
|
COMSIG_AIRLOCK_SHELL_ALLOWED
|
|
))
|
|
return ..()
|
|
|
|
|
|
/obj/item/circuit_component/airlock_access_event/populate_ports()
|
|
open_airlock = add_input_port("Should Open Airlock", PORT_TYPE_RESPONSE_SIGNAL, trigger = PROC_REF(should_open_airlock))
|
|
accessing_entity = add_output_port("Accessing Entity", PORT_TYPE_ATOM)
|
|
event_triggered = add_output_port("Event Triggered", PORT_TYPE_INSTANT_SIGNAL)
|
|
|
|
|
|
/obj/item/circuit_component/airlock_access_event/proc/should_open_airlock(datum/port/input/port, list/return_values)
|
|
CIRCUIT_TRIGGER
|
|
if(!return_values)
|
|
return
|
|
return_values["should_open"] = TRUE
|
|
|
|
/obj/item/circuit_component/airlock_access_event/proc/handle_allowed(datum/source, mob/accesser)
|
|
SIGNAL_HANDLER
|
|
if(!attached_airlock)
|
|
return
|
|
|
|
SScircuit_component.queue_instant_run()
|
|
accessing_entity.set_output(accesser)
|
|
event_triggered.set_output(COMPONENT_SIGNAL)
|
|
var/list/result = SScircuit_component.execute_instant_run()
|
|
|
|
if(!result)
|
|
attached_airlock.visible_message(span_warning("[attached_airlock]'s circuitry overheats!"))
|
|
return
|
|
|
|
if(result["should_open"])
|
|
return COMPONENT_OBJ_ALLOW
|
|
else
|
|
return COMPONENT_OBJ_DISALLOW
|