Files
Bubberstation/code/modules/assembly/doorcontrol.dm
SyncIt21 149ff6f8c3 Multitooling pod door controllers now picks from a list & auto generates new IDs (#92494)
## About The Pull Request
Using a multitool on a pod door assembly controller now displays a list
of doors to choose from instead of typing an ID from `0->100`. You can
only control doors that you have either crafted/linked with an assembly
controller It can also auto generate a unique ID for you to assemble new
doors


https://github.com/user-attachments/assets/0918f1e3-1f22-4cde-b20e-0eb8bb6ba953

## Why It's Good For The Game
Having to no longer remember the ID of doors you created cause the game
now displays that list for you is very convenient. Also generating new
unique IDs without player intervention (which results in errors if you
can't remember the door IDs you typed before) is faster as well.
Not to mention currently if you have created 100 doors you run out of
unique ID's. Now that's no longer the case

## Changelog
🆑
qol: Multitooling a pod door controller now picks from a list of doors
available for that player(crafted, set via controller) only and can auto
generate new IDs for you
/🆑
2025-09-20 00:49:37 +02:00

226 lines
7.7 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"
/// The ID of the blast door electronics to match to the ID of the blast door being used.
var/id = -1
/// Cooldown of the door's controller. Updates when pressed (activate())
var/cooldown = FALSE
/// Should we toggle open/close of doors based on their current state
var/sync_doors = TRUE
/obj/item/assembly/control/Initialize(mapload)
. = ..()
register_context()
/obj/item/assembly/control/add_context(atom/source, list/context, obj/item/held_item, mob/user)
. = NONE
if(istype(held_item, /obj/item/assembly/control))
context[SCREENTIP_CONTEXT_LMB] = "Copy ID"
return CONTEXTUAL_SCREENTIP_SET
/obj/item/assembly/control/examine(mob/user)
. = ..()
if(id)
if(id != -1)
. += span_notice("Its channel ID is '[id]'.")
else
. += span_notice("Interact with pod door to generate an new id")
. += span_notice("You can interact with another controller to copy its ID.")
/obj/item/assembly/control/multitool_act(mob/living/user)
var/list/door_ids = list()
var/list/display_ids = list("UNIQUE")
for(var/obj/machinery/door/poddoor/M as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/door/poddoor))
if(!M.id || (M.id in door_ids))
continue
door_ids += "[M.id]"
if(M.owner?.resolve() != user)
continue
var/area/door_area = get_area(M)
display_ids += "[door_area.name]([M.id])"
var/change_id = tgui_input_list(user, "Set Controller ID", "Controller ID", display_ids)
if(!change_id || QDELETED(user) || QDELETED(src) || !user.can_perform_action(src, FORBID_TELEKINESIS_REACH))
return
if(change_id == "UNIQUE")
id = -1
else
var/start = findtext(change_id, "(") + 1
var/end = length(change_id) - 1
if(start == end)
id = "[change_id[start]]"
else
id = copytext(change_id, start, end)
balloon_alert(user, "id changed")
if(id != -1)
to_chat(user, span_notice("You change the ID to [id]."))
else
to_chat(user, span_notice("You now must interact with an pod door to generate an unique ID."))
/obj/item/assembly/control/interact_with_atom(obj/item/assembly/control/interacting_with, mob/living/user, list/modifiers)
. = NONE
if(istype(interacting_with))
id = interacting_with.id
balloon_alert(user, "id changed")
return ITEM_INTERACT_SUCCESS
/obj/item/assembly/control/activate()
var/openclose
if(cooldown)
return
cooldown = TRUE
for(var/obj/machinery/door/poddoor/M as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/door/poddoor))
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), 1 SECONDS)
/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), 0.5 SECONDS)
/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 as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/door/airlock))
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())
if(D.locked)
D.unlock()
else
D.lock()
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), 1 SECONDS)
/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 as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/door/poddoor))
if (M.id == src.id)
INVOKE_ASYNC(M, TYPE_PROC_REF(/obj/machinery/door/poddoor, open))
addtimer(CALLBACK(src, PROC_REF(activate_stage2)), 1 SECONDS)
/obj/item/assembly/control/massdriver/proc/activate_stage2()
for(var/obj/machinery/mass_driver/M as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/mass_driver))
if(M.id == src.id)
M.drive()
addtimer(CALLBACK(src, PROC_REF(activate_stage3)), 6 SECONDS)
/obj/item/assembly/control/massdriver/proc/activate_stage3()
for(var/obj/machinery/door/poddoor/M as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/door/poddoor))
if (M.id == src.id)
INVOKE_ASYNC(M, TYPE_PROC_REF(/obj/machinery/door/poddoor, close))
addtimer(VARSET_CALLBACK(src, cooldown, FALSE), 1 SECONDS)
/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 as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/sparker))
if (M.id == src.id)
INVOKE_ASYNC(M, TYPE_PROC_REF(/obj/machinery/sparker, ignite))
for(var/obj/machinery/igniter/M as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/igniter))
if(M.id == src.id)
INVOKE_ASYNC(M, TYPE_PROC_REF(/obj/machinery/igniter, toggle))
addtimer(VARSET_CALLBACK(src, cooldown, FALSE), 3 SECONDS)
/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 as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/flasher))
if(M.id == src.id)
INVOKE_ASYNC(M, TYPE_PROC_REF(/obj/machinery/flasher, flash))
addtimer(VARSET_CALLBACK(src, cooldown, FALSE), 5 SECONDS)
/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), 5 SECONDS)