[MIRROR] makes air lock controllers use tgui (#26246)

* makes air lock controllers use tgui (#81050)

## About The Pull Request
makes air lock controllers use tgui

![image](https://github.com/tgstation/tgstation/assets/138636438/a5bba240-d0a2-4bef-b72b-3717e1a13f09)

## Why It's Good For The Game
they will now use tgui instead of html

## Changelog
🆑
refactor: airlock controllers now use tgui
/🆑

* makes air lock controllers use tgui

---------

Co-authored-by: Ben10Omintrix <138636438+Ben10Omintrix@users.noreply.github.com>
This commit is contained in:
SkyratBot
2024-01-25 23:06:47 -05:00
committed by GitHub
co-authored by Ben10Omintrix
parent dc91c9cda5
commit 309da5fd76
3 changed files with 248 additions and 196 deletions
-3
View File
@@ -308,9 +308,6 @@
for(var/obj/machinery/door/airlock/otherlock as anything in close_others)
otherlock.close_others -= src
close_others.Cut()
if(id_tag)
for(var/obj/machinery/door_buttons/D as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/door_buttons))
D.removeMe(src)
QDEL_NULL(note)
QDEL_NULL(seal)
for(var/datum/atom_hud/data/diagnostic/diag_hud in GLOB.huds)
@@ -1,9 +1,3 @@
#define CLOSING 1
#define OPENING 2
#define CYCLE 3
#define CYCLE_EXTERIOR 4
#define CYCLE_INTERIOR 5
/obj/machinery/door_buttons
power_channel = AREA_USAGE_ENVIRON
use_power = IDLE_POWER_USE
@@ -15,7 +9,7 @@
/obj/machinery/door_buttons/attackby(obj/O, mob/user)
return attack_hand(user)
/obj/machinery/door_buttons/proc/findObjsByTag()
/obj/machinery/door_buttons/proc/find_objects_by_tag()
return
/obj/machinery/door_buttons/Initialize(mapload)
@@ -23,7 +17,7 @@
return INITIALIZE_HINT_LATELOAD
/obj/machinery/door_buttons/LateInitialize()
findObjsByTag()
find_objects_by_tag()
/obj/machinery/door_buttons/emag_act(mob/user, obj/item/card/emag/emag_card)
if(obj_flags & EMAGGED)
@@ -35,9 +29,6 @@
balloon_alert(user, "access controller shorted")
return TRUE
/obj/machinery/door_buttons/proc/removeMe()
/obj/machinery/door_buttons/access_button
icon = 'icons/obj/machines/wallmounts.dmi' // SKYRAT EDIT CHANGE - ICON OVERRIDEN BY AESTHETICS - SEE MODULE
icon_state = "access_button_standby"
@@ -49,14 +40,16 @@
var/obj/machinery/door_buttons/airlock_controller/controller
var/busy
/obj/machinery/door_buttons/access_button/findObjsByTag()
/obj/machinery/door_buttons/access_button/find_objects_by_tag()
for(var/obj/machinery/door_buttons/airlock_controller/A as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/door_buttons/airlock_controller))
if(A.idSelf == idSelf)
controller = A
RegisterSignal(controller, COMSIG_PREQDELETED, PROC_REF(remove_object))
break
for(var/obj/machinery/door/airlock/I as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/door/airlock))
if(I.id_tag == idDoor)
door = I
RegisterSignal(door, COMSIG_PREQDELETED, PROC_REF(remove_object))
break
/obj/machinery/door_buttons/access_button/interact(mob/user)
@@ -71,15 +64,15 @@
busy = TRUE
update_appearance()
if(door.density)
if(!controller.exteriorAirlock || !controller.interiorAirlock)
controller.onlyOpen(door)
if(!controller.exterior_airlock || !controller.interior_airlock)
controller.only_open(door)
else
if(controller.exteriorAirlock.density && controller.interiorAirlock.density)
controller.onlyOpen(door)
if(controller.exterior_airlock.density && controller.interior_airlock.density)
controller.only_open(door)
else
controller.cycleClose(door)
controller.cycle_close(door)
else
controller.onlyClose(door)
controller.only_close(door)
use_power(active_power_usage)
addtimer(CALLBACK(src, PROC_REF(not_busy)), 2 SECONDS)
@@ -94,218 +87,185 @@
icon_state = "[base_icon_state]_[busy ? "cycle" : "standby"]"
return ..()
/obj/machinery/door_buttons/access_button/removeMe(obj/O)
if(O == door)
/obj/machinery/door_buttons/access_button/proc/remove_object(datum/source)
SIGNAL_HANDLER
if(source == door)
door = null
return
if(source == controller)
controller = null
/obj/machinery/door_buttons/access_button/Destroy()
door = null
controller = null
return ..()
/obj/machinery/door_buttons/airlock_controller
name = "access console"
desc = "A small console that can cycle opening between two airlocks."
icon = 'icons/obj/machines/wallmounts.dmi'
icon_state = "access_control_standby"
base_icon_state = "access_control"
name = "access console"
desc = "A small console that can cycle opening between two airlocks."
interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN|INTERACT_MACHINE_ALLOW_SILICON|INTERACT_MACHINE_OPEN_SILICON|INTERACT_MACHINE_SET_MACHINE
var/obj/machinery/door/airlock/interiorAirlock
var/obj/machinery/door/airlock/exteriorAirlock
interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN|INTERACT_MACHINE_ALLOW_SILICON|INTERACT_MACHINE_OPEN_SILICON
///the id of the interior airlock
var/idInterior
///the id of the exterior airlock
var/idExterior
///are we currently in use?
var/busy
var/lostPower
///our interior airlock
var/obj/machinery/door/airlock/interior_airlock
///our exterior airlock
var/obj/machinery/door/airlock/exterior_airlock
/obj/machinery/door_buttons/airlock_controller/removeMe(obj/O)
if(O == interiorAirlock)
interiorAirlock = null
else if(O == exteriorAirlock)
exteriorAirlock = null
///set our doors to null upon deletion
/obj/machinery/door_buttons/airlock_controller/proc/remove_door(datum/source)
SIGNAL_HANDLER
/obj/machinery/door_buttons/airlock_controller/Destroy()
for(var/obj/machinery/door_buttons/access_button/A as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/door_buttons/access_button))
if(A.controller == src)
A.controller = null
return ..()
/obj/machinery/door_buttons/airlock_controller/Topic(href, href_list)
if(..())
if(source == interior_airlock)
interior_airlock = null
return
if(busy)
if(source == exterior_airlock)
exterior_airlock = null
///proc called when we want to open doors without any cycling involved
/obj/machinery/door_buttons/airlock_controller/proc/only_open(obj/machinery/door/airlock/target_door)
if(isnull(target_door))
return
if(!allowed(usr))
to_chat(usr, span_warning("Access denied."))
busy = TRUE
update_appearance()
open_door(target_door)
///proc called when we want to close doors without any cycling involved
/obj/machinery/door_buttons/airlock_controller/proc/only_close(obj/machinery/door/airlock/target_door)
if(isnull(target_door))
return
switch(href_list["command"])
if("close_exterior")
onlyClose(exteriorAirlock)
if("close_interior")
onlyClose(interiorAirlock)
if("cycle_exterior")
cycleClose(exteriorAirlock)
if("cycle_interior")
cycleClose(interiorAirlock)
if("open_exterior")
onlyOpen(exteriorAirlock)
if("open_interior")
onlyOpen(interiorAirlock)
busy = TRUE
close_door(target_door)
/obj/machinery/door_buttons/airlock_controller/proc/onlyOpen(obj/machinery/door/airlock/A)
if(A)
busy = CLOSING
update_appearance()
openDoor(A)
/obj/machinery/door_buttons/airlock_controller/proc/onlyClose(obj/machinery/door/airlock/A)
if(A)
busy = CLOSING
closeDoor(A)
/obj/machinery/door_buttons/airlock_controller/proc/closeDoor(obj/machinery/door/airlock/A)
if(A.density)
goIdle()
///proc that handles closing doors
/obj/machinery/door_buttons/airlock_controller/proc/close_door(obj/machinery/door/airlock/target_door, turn_idle_on_terminate = TRUE)
busy = TRUE
if(isnull(target_door) || target_door.density)
go_idle()
return FALSE
update_appearance()
A.safe = FALSE //Door crushies, manual door after all. Set every time in case someone changed it, safe doors can end up waiting forever.
A.unbolt()
if(A.close())
if(machine_stat & NOPOWER || lostPower || !A || QDELETED(A))
goIdle(TRUE)
return FALSE
A.bolt()
goIdle(TRUE)
return TRUE
goIdle(TRUE)
return FALSE
target_door.safe = FALSE //Door crushies, manual door after all. Set every time in case someone changed it, safe doors can end up waiting forever.
target_door.unbolt()
if(!target_door.close() || (machine_stat & NOPOWER))
go_idle()
return FALSE
target_door?.bolt()
/obj/machinery/door_buttons/airlock_controller/proc/cycleClose(obj/machinery/door/airlock/A)
if(!A || !exteriorAirlock || !interiorAirlock)
if(turn_idle_on_terminate)
go_idle()
return TRUE
///proc called when we want to close doors with cycling
/obj/machinery/door_buttons/airlock_controller/proc/cycle_close(obj/machinery/door/airlock/target_door)
if(isnull(exterior_airlock) || isnull(interior_airlock))
return
if(exteriorAirlock.density == interiorAirlock.density || !A.density)
if(exterior_airlock.density == interior_airlock.density || !target_door.density)
return
busy = CYCLE
busy = TRUE
update_appearance()
if(A == interiorAirlock)
if(closeDoor(exteriorAirlock))
busy = CYCLE_INTERIOR
else
if(closeDoor(interiorAirlock))
busy = CYCLE_EXTERIOR
var/obj/machinery/door/airlock/opposite_airlock = (target_door == exterior_airlock ? interior_airlock : exterior_airlock)
/obj/machinery/door_buttons/airlock_controller/proc/cycleOpen(obj/machinery/door/airlock/A)
if(!A)
goIdle(TRUE)
if(A == exteriorAirlock)
if(interiorAirlock)
if(!interiorAirlock.density || !interiorAirlock.locked)
return
else
if(exteriorAirlock)
if(!exteriorAirlock.density || !exteriorAirlock.locked)
return
if(busy != OPENING)
busy = OPENING
openDoor(A)
if(!close_door(opposite_airlock, turn_idle_on_terminate = FALSE))
return go_idle()
/obj/machinery/door_buttons/airlock_controller/proc/openDoor(obj/machinery/door/airlock/A)
if(exteriorAirlock && interiorAirlock && (!exteriorAirlock.density || !interiorAirlock.density))
goIdle(TRUE)
return
A.unbolt()
INVOKE_ASYNC(src, PROC_REF(do_openDoor), A)
addtimer(CALLBACK(src, PROC_REF(cycle_open), target_door), 2 SECONDS)
/obj/machinery/door_buttons/airlock_controller/proc/do_openDoor(obj/machinery/door/airlock/A)
if(A?.open())
if(machine_stat | (NOPOWER) && !lostPower && A && !QDELETED(A))
A.bolt()
goIdle(TRUE)
///proc called when we want to open doors with cycling
/obj/machinery/door_buttons/airlock_controller/proc/cycle_open(obj/machinery/door/airlock/target_door)
if(isnull(target_door))
return go_idle()
var/obj/machinery/door/airlock/opposite_airlock = (target_door == exterior_airlock ? interior_airlock : exterior_airlock)
if(isnull(opposite_airlock) || !opposite_airlock.density || !opposite_airlock.locked)
return go_idle()
busy = TRUE
open_door(target_door)
/obj/machinery/door_buttons/airlock_controller/proc/goIdle(update)
lostPower = FALSE
///proc that handles opening and unbolting the door
/obj/machinery/door_buttons/airlock_controller/proc/open_door(obj/machinery/door/airlock/target_door)
if(!target_door.density)
return go_idle()
target_door.unbolt()
if(!target_door.open() || (machine_stat & NOPOWER))
return go_idle()
target_door?.bolt()
return go_idle()
///unsets our busy state and update our appearance
/obj/machinery/door_buttons/airlock_controller/proc/go_idle()
busy = FALSE
if(update)
update_appearance()
updateUsrDialog()
update_appearance()
/obj/machinery/door_buttons/airlock_controller/process()
if(machine_stat & NOPOWER)
return
if(busy == CYCLE_EXTERIOR)
cycleOpen(exteriorAirlock)
else if(busy == CYCLE_INTERIOR)
cycleOpen(interiorAirlock)
/obj/machinery/door_buttons/airlock_controller/power_change()
. = ..()
if(machine_stat & NOPOWER)
lostPower = TRUE
else
if(!busy)
lostPower = FALSE
/obj/machinery/door_buttons/airlock_controller/findObjsByTag()
/obj/machinery/door_buttons/airlock_controller/find_objects_by_tag()
for(var/obj/machinery/door/door as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/door))
if(isnull(idInterior) || isnull(idExterior))
break
if(door.id_tag == idInterior)
interiorAirlock = door
else if(door.id_tag == idExterior)
exteriorAirlock = door
interior_airlock = door
RegisterSignal(interior_airlock, COMSIG_PREQDELETED, PROC_REF(remove_door))
if(door.id_tag == idExterior)
exterior_airlock = door
RegisterSignal(exterior_airlock, COMSIG_PREQDELETED, PROC_REF(remove_door))
/obj/machinery/door_buttons/airlock_controller/update_icon_state()
if(machine_stat & NOPOWER)
icon_state = "access_control_off"
icon_state = "[base_icon_state]_off"
return ..()
icon_state = "[base_icon_state]_[(busy || lostPower) ? "process" : "standby"]"
icon_state = "[base_icon_state]_[(busy) ? "process" : "standby"]"
return ..()
/obj/machinery/door_buttons/airlock_controller/ui_interact(mob/user)
var/datum/browser/popup = new(user, "computer", name)
popup.set_content(returnText())
popup.open()
/obj/machinery/door_buttons/airlock_controller/ui_interact(mob/user, datum/tgui/ui)
. = ..()
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "AirlockButtonController", name)
ui.open()
/obj/machinery/door_buttons/airlock_controller/proc/returnText()
var/output
if(!exteriorAirlock && !interiorAirlock)
return "ERROR ERROR ERROR ERROR"
if(lostPower)
output = "Initializing..."
/obj/machinery/door_buttons/airlock_controller/ui_data(mob/user)
var/list/data = list()
data["interior_door"] = interior_airlock ? REF(interior_airlock) : null
data["exterior_door"] = exterior_airlock ? REF(exterior_airlock) : null
data["busy"] = busy
data["interior_door_closed"] = interior_airlock?.density
data["exterior_door_closed"] = exterior_airlock?.density
return data
/obj/machinery/door_buttons/airlock_controller/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
. = ..()
if(. || busy)
return TRUE
if(isnull(params["requested_door"]))
return TRUE
var/atom/requested_door
var/atom/opposite_door
if(REF(interior_airlock) == params["requested_door"])
requested_door = interior_airlock
opposite_door = exterior_airlock
else
if(!exteriorAirlock || !interiorAirlock)
if(!exteriorAirlock)
if(interiorAirlock.density)
output = "<A href='?src=[REF(src)];command=open_interior'>Open Interior Airlock</A><BR>"
else
output = "<A href='?src=[REF(src)];command=close_interior'>Close Interior Airlock</A><BR>"
requested_door = exterior_airlock
opposite_door = interior_airlock
switch(action)
if("open")
if(opposite_door && !opposite_door.density)
cycle_close(requested_door)
else
if(exteriorAirlock.density)
output = "<A href='?src=[REF(src)];command=open_exterior'>Open Exterior Airlock</A><BR>"
else
output = "<A href='?src=[REF(src)];command=close_exterior'>Close Exterior Airlock</A><BR>"
else
if(exteriorAirlock.density)
if(interiorAirlock.density)
output = {"<A href='?src=[REF(src)];command=open_exterior'>Open Exterior Airlock</A><BR>
<A href='?src=[REF(src)];command=open_interior'>Open Interior Airlock</A><BR>"}
else
output = {"<A href='?src=[REF(src)];command=cycle_exterior'>Cycle to Exterior Airlock</A><BR>
<A href='?src=[REF(src)];command=close_interior'>Close Interior Airlock</A><BR>"}
else
if(interiorAirlock.density)
output = {"<A href='?src=[REF(src)];command=close_exterior'>Close Exterior Airlock</A><BR>
<A href='?src=[REF(src)];command=cycle_interior'>Cycle to Interior Airlock</A><BR>"}
else
output = {"<A href='?src=[REF(src)];command=close_exterior'>Close Exterior Airlock</A><BR>
<A href='?src=[REF(src)];command=close_interior'>Close Interior Airlock</A><BR>"}
only_open(requested_door)
if("close")
only_close(requested_door)
output = {"<B>Access Control Console</B><HR>
[output]<HR>"}
if(exteriorAirlock)
output += "<B>Exterior Door: </B> [exteriorAirlock.density ? "closed" : "open"]<BR>"
if(interiorAirlock)
output += "<B>Interior Door: </B> [interiorAirlock.density ? "closed" : "open"]<BR>"
return output
#undef CLOSING
#undef OPENING
#undef CYCLE
#undef CYCLE_EXTERIOR
#undef CYCLE_INTERIOR
return TRUE
@@ -0,0 +1,95 @@
import { BooleanLike } from 'common/react';
import { useBackend } from '../backend';
import { Button, NoticeBox, Section, Stack } from '../components';
import { Window } from '../layouts';
type Data = {
interior_door: string;
exterior_door: string;
interior_door_closed: BooleanLike;
exterior_door_closed: BooleanLike;
busy: BooleanLike;
};
export const AirlockButtonController = (props) => {
const { data } = useBackend<Data>();
const { interior_door, exterior_door } = data;
return (
<Window width={500} height={130}>
<Window.Content>
<Section title="Airlock Controller" textAlign="center">
{!interior_door && !exterior_door ? (
<NoticeBox danger>No doors detected</NoticeBox>
) : (
<Stack>
{interior_door && (
<Stack.Item grow textAlign="center">
<RetrieveButton airlockType={interior_door} />
</Stack.Item>
)}
{exterior_door && (
<Stack.Item grow textAlign="center">
<RetrieveButton airlockType={exterior_door} />
</Stack.Item>
)}
</Stack>
)}
</Section>
</Window.Content>
</Window>
);
};
const RetrieveButton = (props) => {
const { act, data } = useBackend<Data>();
const {
interior_door,
exterior_door,
interior_door_closed,
exterior_door_closed,
busy,
} = data;
const { airlockType } = props;
const our_door_closed =
airlockType === interior_door ? interior_door_closed : exterior_door_closed;
const opposite_door_closed =
airlockType === interior_door ? exterior_door_closed : interior_door_closed;
const opposite_door =
airlockType === interior_door ? exterior_door : interior_door;
return (
<Button
mt={2}
icon={our_door_closed ? 'lock-open' : 'lock'}
color="green"
fontSize={1.5}
textAlign="center"
lineHeight="1.5"
disabled={busy}
onClick={() => {
if (!our_door_closed) {
act('close', {
requested_door: airlockType,
});
} else {
act('open', {
requested_door: airlockType,
});
}
}}
>
{!our_door_closed
? `Close ${
airlockType === interior_door ? 'interior door' : 'exterior door'
}`
: !opposite_door_closed && opposite_door
? `Cycle to ${
airlockType === interior_door ? 'interior door' : 'exterior door'
}`
: `Open ${
airlockType === interior_door ? 'interior door' : 'exterior door'
}`}
</Button>
);
};