Files
Bubberstation/code/modules/assembly/doorcontrol.dm
SkyratBot c096a04bad [MIRROR] Minor improvement to blast door construction. [MDB IGNORE] (#19191)
* Minor improvement to blast door construction. (#73038)

## About The Pull Request

This PR does some QOL tweaks to blast doors and their construction.
Namely, adding some balloon alerts to the whole construction process
(adding, removing electronics, adjusting their electronics IDs).

Additionally, adds some extra examine text to an open blast door by
explaining that you can multitool it to adjust the ID, and that it must
match that of the blast electronics to be added to a wall frame.

Adjusts a forcedrop to a `move_to_hands` because it's 2023 and we trust
that users can hold things during a attack_hand proc.

Also adds some description to button frames as well to guide them that
they can install and remove electronics and boards while open.

I'm gonna be real, this needs a LOT more work than this to be up to code
standards, but this was what I could pull off in the 30 minutes before I
need to sleep while away on business, but it's a start nonetheless.

## Why It's Good For The Game

Button frame code is practically ancient, yet it's still widely used to
this day. It needs some real polish more than this, but for now this
will at least make the construction process more intuitive and clear.

Also to that guy who I said I would do this about a month ago I'M SORRY
I'VE BEEN TRAPPED IN THE **_SUPERMAX WAGE CAGE_** I CAN PROVE IT

~~Wait what do you mean you need to make player made blast doors through
the CRAFTING UI WHAT THE FUUUUUUUU~~

## Changelog

🆑
qol: Improves feedback on buttons as well as the blast door electronics
so that installing your very own blast doors is less tedious.
/🆑

* Minor improvement to blast door construction.

---------

Co-authored-by: ArcaneMusic <41715314+ArcaneMusic@users.noreply.github.com>
Co-authored-by: lessthanthree <83487515+lessthnthree@users.noreply.github.com>
2023-02-12 02:26:28 -08:00

235 lines
7.4 KiB
Plaintext

/obj/item/assembly/control
name = "blast door controller"
desc = "A small electronic device able to control a blast door remotely."
icon_state = "control"
attachable = TRUE
/// The ID of the blast door electronics to match to the ID of the blast door being used.
var/id = null
/// Cooldown of the door's controller. Updates when pressed (activate())
var/cooldown = FALSE
var/sync_doors = TRUE
/obj/item/assembly/control/examine(mob/user)
. = ..()
if(id)
. += span_notice("Its channel ID is '[id]'.")
/obj/item/assembly/control/multitool_act(mob/living/user)
var/change_id = tgui_input_number(user, "Set the door controllers ID", "Door ID", id, 100)
if(!change_id || QDELETED(user) || QDELETED(src) || !usr.canUseTopic(src, be_close = TRUE, no_dexterity = FALSE, no_tk = TRUE))
return
id = change_id
balloon_alert(user, "id changed")
to_chat(user, span_notice("You change the ID to [id]."))
/obj/item/assembly/control/activate()
var/openclose
if(cooldown)
return
cooldown = TRUE
for(var/obj/machinery/door/poddoor/M in GLOB.airlocks)
if(M.id == src.id)
if(openclose == null || !sync_doors)
openclose = M.density
INVOKE_ASYNC(M, openclose ? TYPE_PROC_REF(/obj/machinery/door/poddoor, open) : TYPE_PROC_REF(/obj/machinery/door/poddoor, close))
addtimer(VARSET_CALLBACK(src, cooldown, FALSE), 10)
/obj/item/assembly/control/curtain
name = "curtain controller"
desc = "A small electronic device able to control a mechanical curtain remotely."
/obj/item/assembly/control/curtain/examine(mob/user)
. = ..()
if(id)
. += span_notice("Its channel ID is '[id]'.")
/obj/item/assembly/control/curtain/activate()
var/openclose
if(cooldown)
return
cooldown = TRUE
for(var/obj/structure/curtain/cloth/fancy/mechanical/M in GLOB.curtains)
if(M.id == src.id)
if(openclose == null || !sync_doors)
openclose = M.density
INVOKE_ASYNC(M, openclose ? TYPE_PROC_REF(/obj/structure/curtain/cloth/fancy/mechanical, open) : TYPE_PROC_REF(/obj/structure/curtain/cloth/fancy/mechanical, close))
addtimer(VARSET_CALLBACK(src, cooldown, FALSE), 5)
/obj/item/assembly/control/airlock
name = "airlock controller"
desc = "A small electronic device able to control an airlock remotely."
id = "badmin" // Set it to null for MEGAFUN.
var/specialfunctions = OPEN
/*
Bitflag, 1= open (OPEN)
2= idscan (IDSCAN)
4= bolts (BOLTS)
8= shock (SHOCK)
16= door safties (SAFE)
*/
/obj/item/assembly/control/airlock/activate()
if(cooldown)
return
cooldown = TRUE
var/doors_need_closing = FALSE
var/list/obj/machinery/door/airlock/open_or_close = list()
for(var/obj/machinery/door/airlock/D in GLOB.airlocks)
if(D.id_tag == src.id)
if(specialfunctions & OPEN)
open_or_close += D
if(!D.density)
doors_need_closing = TRUE
if(specialfunctions & IDSCAN)
D.aiDisabledIdScanner = !D.aiDisabledIdScanner
if(specialfunctions & BOLTS)
if(!D.wires.is_cut(WIRE_BOLTS) && D.hasPower())
D.locked = !D.locked
D.update_appearance()
if(specialfunctions & SHOCK)
if(D.secondsElectrified)
D.set_electrified(MACHINE_ELECTRIFIED_PERMANENT, usr)
else
D.set_electrified(MACHINE_NOT_ELECTRIFIED, usr)
if(specialfunctions & SAFE)
D.safe = !D.safe
for(var/D in open_or_close)
INVOKE_ASYNC(D, doors_need_closing ? TYPE_PROC_REF(/obj/machinery/door/airlock, close) : TYPE_PROC_REF(/obj/machinery/door/airlock, open))
addtimer(VARSET_CALLBACK(src, cooldown, FALSE), 10)
/obj/item/assembly/control/massdriver
name = "mass driver controller"
desc = "A small electronic device able to control a mass driver."
/obj/item/assembly/control/massdriver/activate()
if(cooldown)
return
cooldown = TRUE
for(var/obj/machinery/door/poddoor/M in GLOB.airlocks)
if (M.id == src.id)
INVOKE_ASYNC(M, TYPE_PROC_REF(/obj/machinery/door/poddoor, open))
sleep(1 SECONDS)
for(var/obj/machinery/mass_driver/M in GLOB.machines)
if(M.id == src.id)
M.drive()
sleep(6 SECONDS)
for(var/obj/machinery/door/poddoor/M in GLOB.airlocks)
if (M.id == src.id)
INVOKE_ASYNC(M, TYPE_PROC_REF(/obj/machinery/door/poddoor, close))
addtimer(VARSET_CALLBACK(src, cooldown, FALSE), 10)
/obj/item/assembly/control/igniter
name = "ignition controller"
desc = "A remote controller for a mounted igniter."
/obj/item/assembly/control/igniter/activate()
if(cooldown)
return
cooldown = TRUE
for(var/obj/machinery/sparker/M in GLOB.machines)
if (M.id == src.id)
INVOKE_ASYNC(M, TYPE_PROC_REF(/obj/machinery/sparker, ignite))
for(var/obj/machinery/igniter/M in GLOB.machines)
if(M.id == src.id)
M.use_power(50)
M.on = !M.on
M.icon_state = "igniter[M.on]"
addtimer(VARSET_CALLBACK(src, cooldown, FALSE), 30)
/obj/item/assembly/control/flasher
name = "flasher controller"
desc = "A remote controller for a mounted flasher."
/obj/item/assembly/control/flasher/activate()
if(cooldown)
return
cooldown = TRUE
for(var/obj/machinery/flasher/M in GLOB.machines)
if(M.id == src.id)
INVOKE_ASYNC(M, TYPE_PROC_REF(/obj/machinery/flasher, flash))
addtimer(VARSET_CALLBACK(src, cooldown, FALSE), 50)
/obj/item/assembly/control/crematorium
name = "crematorium controller"
desc = "An evil-looking remote controller for a crematorium."
/obj/item/assembly/control/crematorium/activate()
if(cooldown)
return
cooldown = TRUE
for (var/obj/structure/bodycontainer/crematorium/C in GLOB.crematoriums)
if (C.id == id)
C.cremate(usr)
addtimer(VARSET_CALLBACK(src, cooldown, FALSE), 50)
/obj/item/assembly/control/tram
name = "tram call button"
desc = "A small device used to bring trams to you."
///for finding the landmark initially - should be the exact same as the landmark's destination id.
var/initial_id
///ID to link to allow us to link to one specific tram in the world
var/specific_lift_id = MAIN_STATION_TRAM
///this is our destination's landmark, so we only have to find it the first time.
var/datum/weakref/to_where
/obj/item/assembly/control/tram/Initialize(mapload)
..()
return INITIALIZE_HINT_LATELOAD
/obj/item/assembly/control/tram/LateInitialize()
. = ..()
//find where the tram needs to go to (our destination). only needs to happen the first time
for(var/obj/effect/landmark/tram/our_destination as anything in GLOB.tram_landmarks[specific_lift_id])
if(our_destination.destination_id == initial_id)
to_where = WEAKREF(our_destination)
break
/obj/item/assembly/control/tram/Destroy()
to_where = null
return ..()
/obj/item/assembly/control/tram/activate()
if(cooldown)
return
cooldown = TRUE
addtimer(VARSET_CALLBACK(src, cooldown, FALSE), 2 SECONDS)
var/datum/lift_master/tram/tram
for(var/datum/lift_master/tram/possible_match as anything in GLOB.active_lifts_by_type[TRAM_LIFT_ID])
if(possible_match.specific_lift_id == specific_lift_id)
tram = possible_match
break
if(!tram || !tram.is_operational) //tram is QDEL or has no power
say("The tram is not in service. Please send a technician to repair the internals of the tram.")
return
if(tram.travelling) //in use
say("The tram is already travelling to [tram.from_where].")
return
if(!to_where)
return
var/obj/effect/landmark/tram/current_location = to_where.resolve()
if(!current_location)
return
if(tram.from_where == current_location) //already here
say("The tram is already here. Please board the tram and select a destination.")
return
say("The tram has been called to [current_location.name]. Please wait for its arrival.")
tram.tram_travel(current_location)