mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-10 23:54:14 +01:00
c7e7257d9a
## About The Pull Request Constructable atmospheric floor igniters (as introduced in PR #75722 by @SyncIt21) seem to have been broken last year with PR #92494. All button-bound controllers (igniter, airlock, crematorium, curtain, et cetera) are currently subtypes of blast door controllers. Accordingly, the `multitool_act()` proc from the latter PR both broke and erroneously introduced blast door ID-setting functionality to every subtype. <details><summary>Faulty <code>examine()</code> for example:</summary> <img width="415" height="121" alt="Ignition_Controller_Desc" src="https://github.com/user-attachments/assets/ce7b038a-035a-45b1-85f9-1c78ad9b8b63" /> </details> This PR fixes floor igniters by refactoring blast door controllers into their own subtype of a generic parent type. A few minor grammar corrections have also been included. ## Why It's Good For The Game There are a lot of different wall buttons in-game that do a lot of different things. Many of those things are far removed from blast doors. Having blast door controllers be the parent type for all other controllers is then likely to cause future problems. Nothing more exemplifies this than the problem fixed here. ## Changelog 🆑 fix: Fixed floor igniters and ensured that they are linkable to constructed buttons. fix: All wall-mounted button electronics are no longer arbitrarily alterable with blast doors. refactor: Refactored blast doors controllers into their own subtype of a new abstract controller type. /🆑
256 lines
8.7 KiB
Plaintext
256 lines
8.7 KiB
Plaintext
/obj/item/assembly/control
|
|
name = "controller assembly"
|
|
desc = "An assembly that controls something. It's so vaguely designed that it probably shouldn't exist."
|
|
icon_state = "control"
|
|
/// The ID of the electronics to match to the ID of the machine being used.
|
|
var/id = -1
|
|
/// Cooldown of the controller. Updates when pressed (activate())
|
|
var/cooldown = FALSE
|
|
/// Should we toggle open/close of doors based on their current state
|
|
/// Also used for curtains
|
|
var/sync_doors = TRUE
|
|
/// If this controller's ID should be adjustable by players through multitools.
|
|
var/generically_adjustable = FALSE
|
|
/// If this controller's ID should be copyable by hitting with an identical controller.
|
|
var/copyable = FALSE
|
|
|
|
/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, type) && copyable)
|
|
context[SCREENTIP_CONTEXT_LMB] = "Copy ID"
|
|
return CONTEXTUAL_SCREENTIP_SET
|
|
|
|
/obj/item/assembly/control/examine(mob/user)
|
|
. = ..()
|
|
if(generically_adjustable)
|
|
. += span_notice("You can use a [EXAMINE_HINT("multitool")] to adjust its ID.")
|
|
|
|
if(copyable)
|
|
. += span_notice("You can interact with another controller to copy its ID.")
|
|
|
|
if(!id)
|
|
return
|
|
|
|
if(id != -1)
|
|
. += span_notice("Its channel ID is '[id]'.")
|
|
|
|
/obj/item/assembly/control/multitool_act(mob/living/user)
|
|
if(!generically_adjustable)
|
|
return
|
|
|
|
var/change_id = tgui_input_number(user, "Set the [name]'s ID", "Controller ID", id, 100)
|
|
if(!change_id || QDELETED(user) || QDELETED(src) || !usr.can_perform_action(src, FORBID_TELEKINESIS_REACH))
|
|
return
|
|
id = change_id
|
|
to_chat(user, span_notice("You change the ID to [id]."))
|
|
|
|
/obj/item/assembly/control/interact_with_atom(obj/item/assembly/control/interacting_with, mob/living/user, list/modifiers)
|
|
. = NONE
|
|
if(!copyable)
|
|
return
|
|
|
|
if(istype(interacting_with))
|
|
id = interacting_with.id
|
|
balloon_alert(user, "id changed")
|
|
return ITEM_INTERACT_SUCCESS
|
|
|
|
/obj/item/assembly/control/blast_door
|
|
name = "blast door controller"
|
|
desc = "A small electronic device able to control blast doors or shutters remotely."
|
|
copyable = TRUE
|
|
|
|
/obj/item/assembly/control/blast_door/examine(mob/user)
|
|
. = ..()
|
|
if(id && id == -1)
|
|
. += span_notice("Interact with a blast door or shutter to generate a new ID")
|
|
|
|
/obj/item/assembly/control/blast_door/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 a pod door to generate a unique ID."))
|
|
|
|
/obj/item/assembly/control/blast_door/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/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 floor igniter or wall sparker."
|
|
generically_adjustable = TRUE
|
|
copyable = TRUE
|
|
|
|
/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)
|