Files
Bubberstation/code/modules/wiremod/shell/airlock.dm
LemonInTheDark 830d2e50b4 Fixes some stupid airlock sleeps (#75961)
## About The Pull Request

[A common problem with explosions is an overabundance of
sleeping](6499077a09)

In an attempt to solve this issue, let's not continue to sleep and do
work in door closing if the door is already deleted

(This is caused by firelocks activating due to other adjacent objects
deleting, triggering an atmos update, and closing the firelocks before
they get bombed. I don't have a elegant way of resolving that core
problem, so let's just minimize the impact)

[Nukes a stupid sleep loop in airlock
code](5b16360520)

When an airlock was depowered, it would enter a sleep loop, decrementing
its delay by 1 second every well, one second, so long as it had the
right wires flipped
This is very stupid

Instead, let's use signals off wire changes and a combo of timer and
remaining time var to do this with JUST a timer

Most of the changes here are just swapping over wires to a setter to
make signal registration work\

## Why It's Good For The Game

Less sleeping around explosions means less dropped ticks after a bomb
goes off. Good just in general
Also this excises dumb boomer code and adds some hooks for other devs to
use (we should use wires more man)
2023-06-19 02:18:48 +00:00

203 lines
6.5 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)
// 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), \
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