Files
LordMEandGitHub 9f7962c1ca Reworks airlock programs (#6271)
<!-- Write **BELOW** The Headers and **ABOVE** The comments else it may
not be viewable. -->
<!-- You can view Contributing.MD for a detailed description of the pull
request process. -->

## About The Pull Request
In the old version Airlock controllers used a badly implemented system
for determining what to do.
This PR reworks that system to use a set of defined states, in which the
airlock can be.
There is two kinds of states, stable and transforming. 
Stable states stay the same unless an order is given.
Transforming states are actively altering the contents of the airlock
chamber, like pressurizing.
This system allows for for more reliable and predictable behaviour of
airlocks.
<!-- Describe The Pull Request. Please be sure every change is
documented or this can delay review and even discourage maintainers from
merging your PR! -->

## Why It's Good For The Game
A key system for Space stations should be reliable and behave
predicatable. The system that is replaced in this PR was not
predicatable.
<!-- Argue for the merits of your changes and how they benefit the game,
especially if they are controversial and/or far reaching. If you can't
actually explain WHY what you are doing will improve the game, then it
probably isn't good for the game in the first place. -->

## Changelog

<!-- If your PR modifies aspects of the game that can be concretely
observed by players or admins you should add a changelog. If your change
does NOT meet this description, remove this section. Be sure to properly
mark your PRs to prevent unnecessary GBP loss. You can read up on GBP
and it's effects on PRs in the tgstation guides for contributors. Please
note that maintainers freely reserve the right to remove and add tags
should they deem it appropriate. You can attempt to finagle the system
all you want, but it's best to shoot for clear communication right off
the bat. -->

🆑
code: Airlocks now use properly implemented statemachines
/🆑

<!-- Both 🆑's are required for the changelog to work! You can put
your name to the right of the first 🆑 if you want to overwrite your
GitHub username as author ingame. -->
<!-- You can use multiple of the same prefix (they're only used for the
icon ingame) and delete the unneeded ones. Despite some of the tags,
changelogs should generally represent how a player might be affected by
the changes rather than a summary of the PR's contents. -->
2024-01-20 11:19:21 -08:00

224 lines
7.1 KiB
Plaintext

/*
These programs are for docking controllers that consist of multiple independent airlocks
Each airlock has an airlock controller running the child program, and there is one docking controller running the master program
*/
/*
the master program
*/
/datum/computer/file/embedded_program/docking/multi
var/list/children_tags
var/list/children_ready
var/list/children_override
/datum/computer/file/embedded_program/docking/multi/New(var/obj/machinery/embedded_controller/M)
..(M)
if (istype(M,/obj/machinery/embedded_controller/radio/docking_port_multi)) //if our parent controller is the right type, then we can auto-init stuff at construction
var/obj/machinery/embedded_controller/radio/docking_port_multi/controller = M
//parse child_tags_txt and create child tags
children_tags = splittext(controller.child_tags_txt, ";")
children_ready = list()
children_override = list()
for (var/child_tag in children_tags)
children_ready[child_tag] = 0
children_override[child_tag] = "disabled"
/datum/computer/file/embedded_program/docking/multi/proc/clear_children_ready_status()
for (var/child_tag in children_tags)
children_ready[child_tag] = 0
/datum/computer/file/embedded_program/docking/multi/receive_signal(datum/signal/signal, receive_method, receive_param)
var/receive_tag = signal.data["tag"] //for docking signals, this is the sender id
var/command = signal.data["command"]
var/recipient = signal.data["recipient"] //the intended recipient of the docking signal
if (receive_tag in children_tags)
//track children status
if (signal.data["override_status"])
children_override[receive_tag] = signal.data["override_status"]
if (recipient == id_tag)
switch (command)
if ("ready_for_docking")
children_ready[receive_tag] = 1
if ("ready_for_undocking")
children_ready[receive_tag] = 1
if ("status_override_enabled")
children_override[receive_tag] = 1
if ("status_override_disabled")
children_override[receive_tag] = 0
..(signal, receive_method, receive_param)
/datum/computer/file/embedded_program/docking/multi/prepare_for_docking()
//clear children ready status
clear_children_ready_status()
//tell children to prepare for docking
for (var/child_tag in children_tags)
send_docking_command(child_tag, "prepare_for_docking")
/datum/computer/file/embedded_program/docking/multi/ready_for_docking()
//check children ready status
for (var/child_tag in children_tags)
if (!children_ready[child_tag])
return 0
return 1
/datum/computer/file/embedded_program/docking/multi/finish_docking()
//tell children to finish docking
for (var/child_tag in children_tags)
send_docking_command(child_tag, "finish_docking")
//clear ready flags
clear_children_ready_status()
/datum/computer/file/embedded_program/docking/multi/prepare_for_undocking()
//clear children ready status
clear_children_ready_status()
//tell children to prepare for undocking
for (var/child_tag in children_tags)
send_docking_command(child_tag, "prepare_for_undocking")
/datum/computer/file/embedded_program/docking/multi/ready_for_undocking()
//check children ready status
for (var/child_tag in children_tags)
if (!children_ready[child_tag])
return 0
return 1
/datum/computer/file/embedded_program/docking/multi/finish_undocking()
//tell children to finish undocking
for (var/child_tag in children_tags)
send_docking_command(child_tag, "finish_undocking")
//clear ready flags
clear_children_ready_status()
/*
the child program
technically should be "slave" but eh... I'm too politically correct.
*/
/datum/computer/file/embedded_program/airlock/multi_docking
var/master_tag
var/master_status = "undocked"
var/override_enabled = 0
var/docking_enabled = 0
var/docking_mode = 0 //0 = docking, 1 = undocking
var/response_sent = 0
/datum/computer/file/embedded_program/airlock/multi_docking/New(var/obj/machinery/embedded_controller/M)
..(M)
if (istype(M, /obj/machinery/embedded_controller/radio/airlock/docking_port_multi)) //if our parent controller is the right type, then we can auto-init stuff at construction
var/obj/machinery/embedded_controller/radio/airlock/docking_port_multi/controller = M
src.master_tag = controller.master_tag
/datum/computer/file/embedded_program/airlock/multi_docking/receive_user_command(command)
if (command == "toggle_override")
if (override_enabled)
override_enabled = 0
broadcast_override_status()
else
override_enabled = 1
broadcast_override_status()
return
if (!docking_enabled|| override_enabled) //only allow the port to be used as an airlock if nothing is docked here or the override is enabled
..(command)
/datum/computer/file/embedded_program/airlock/multi_docking/receive_signal(datum/signal/signal, receive_method, receive_param)
..()
var/receive_tag = signal.data["tag"] //for docking signals, this is the sender id
var/command = signal.data["command"]
var/recipient = signal.data["recipient"] //the intended recipient of the docking signal
if (receive_tag != master_tag)
return //only respond to master
//track master's status
if (signal.data["dock_status"])
master_status = signal.data["dock_status"]
if (recipient != id_tag)
return //this signal is not for us
switch (command)
if ("prepare_for_docking")
docking_enabled = 1
docking_mode = 0
response_sent = 0
if (!override_enabled)
return
//begin_cycle_in()
if ("prepare_for_undocking")
docking_mode = 1
response_sent = 0
if (!override_enabled)
//stop_cycling()
close_doors()
disable_mech_regulation()
if ("finish_docking")
if (!override_enabled)
enable_mech_regulation()
open_doors()
if ("finish_undocking")
docking_enabled = 0
/datum/computer/file/embedded_program/airlock/multi_docking/process()
..()
if (docking_enabled && !response_sent)
switch (docking_mode)
if (0) //docking
if (ready_for_docking())
send_signal_to_master("ready_for_docking")
response_sent = 1
if (1) //undocking
if (ready_for_undocking())
send_signal_to_master("ready_for_undocking")
response_sent = 1
//checks if we are ready for docking
/datum/computer/file/embedded_program/airlock/multi_docking/proc/ready_for_docking()
return 0
//checks if we are ready for undocking
/datum/computer/file/embedded_program/airlock/multi_docking/proc/ready_for_undocking()
return 0
/datum/computer/file/embedded_program/airlock/multi_docking/proc/open_doors()
toggleDoor(memory["interior_status"], tag_interior_door, memory["secure"], "open")
toggleDoor(memory["exterior_status"], tag_exterior_door, memory["secure"], "open")
/datum/computer/file/embedded_program/airlock/multi_docking/proc/cycleDoors(var/target)
return 0
/datum/computer/file/embedded_program/airlock/multi_docking/proc/send_signal_to_master(var/command)
var/datum/signal/signal = new
signal.data["tag"] = id_tag
signal.data["command"] = command
signal.data["recipient"] = master_tag
post_signal(signal)
/datum/computer/file/embedded_program/airlock/multi_docking/proc/broadcast_override_status()
var/datum/signal/signal = new
signal.data["tag"] = id_tag
signal.data["override_status"] = override_enabled? "enabled" : "disabled"
post_signal(signal)