From c2e0d21c7aa889e1f27411e77a966d2b38ca501e Mon Sep 17 00:00:00 2001 From: moocowswag <62126254+moocowswag@users.noreply.github.com> Date: Thu, 19 Jun 2025 10:16:47 -0400 Subject: [PATCH] Adds Modular shield consoles, boards, and tech, lets monkeys mash their keyboards (#91189) ## About The Pull Request (had to cut off the video cause of github file size limit) https://github.com/user-attachments/assets/f6a51d28-dc35-41ad-93ac-099c48215013 Adds modular shield generator consoles to the game, boards are available through holographics tech Simply multitool buffer a generator and then use the buffer on a console. The console can see the current shield health status of every generator that is linked to it and can toggle the generators on and off, but cannot change radius or any other settings. The console can also rename generators for convenience And should a monkey manage to slip past your defenses via ventcrawl it will be able to randomly toggle your shields. https://github.com/user-attachments/assets/94435d15-e52f-45c7-a2e6-135228e7bc08 ## Why It's Good For The Game Helps engineers keep track of their generators for primarily PVE content (mainly when they are trying to protect the station against meteors) ## Changelog :cl: add: You can now remotely monitor and control modular shield generators using modular shield generator consoles. /:cl: --------- Co-authored-by: SyncIt21 <110812394+SyncIt21@users.noreply.github.com> Co-authored-by: Jeremiah <42397676+jlsnow301@users.noreply.github.com> Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com> --- .../game/machinery/computer/modular_shield.dm | 74 ++++++++++ code/game/machinery/modular_shield.dm | 8 ++ .../circuitboards/computer_circuitboards.dm | 5 + .../research/designs/machine_designs.dm | 10 ++ .../research/techweb/nodes/engi_nodes.dm | 1 + tgstation.dme | 1 + .../tgui/interfaces/ModularShieldConsole.tsx | 128 ++++++++++++++++++ 7 files changed, 227 insertions(+) create mode 100644 code/game/machinery/computer/modular_shield.dm create mode 100644 tgui/packages/tgui/interfaces/ModularShieldConsole.tsx diff --git a/code/game/machinery/computer/modular_shield.dm b/code/game/machinery/computer/modular_shield.dm new file mode 100644 index 00000000000..dd80553bf39 --- /dev/null +++ b/code/game/machinery/computer/modular_shield.dm @@ -0,0 +1,74 @@ +/obj/machinery/computer/modular_shield + name = "modular shield control console" + desc = "Used to remotely monitor and toggle modular shield generators." + circuit = /obj/item/circuitboard/computer/modular_shield_console + + ///the list of generators that are linked to us + var/list/obj/machinery/modular_shield_generator/generators = list() + +//lets monkeys randomly mash buttons to toggle the generators +/obj/machinery/computer/modular_shield/attack_paw(mob/user, list/modifiers) + balloon_alert(user, "mashing buttons") + if(!do_after(user, 4 SECONDS, target = src)) + return + for(var/obj/machinery/modular_shield_generator/generator as anything in generators) + if(prob(50)) + generator.toggle_shields() + +/obj/machinery/computer/modular_shield/multitool_act(mob/living/user, obj/item/multitool/tool) + . = NONE + if(!istype(tool.buffer, /obj/machinery/modular_shield_generator)) + return + + generators |= tool.buffer + RegisterSignal(tool.buffer, COMSIG_QDELETING, PROC_REF(generator_deleted)) + tool.set_buffer(null) + to_chat(user, span_notice("You upload the data from the [tool] buffer.")) + return ITEM_INTERACT_SUCCESS + +///checks if all connected generators exist +/obj/machinery/computer/modular_shield/proc/generator_deleted(obj/machinery/modular_shield_generator/generator) + SIGNAL_HANDLER + generators -= generator + +/obj/machinery/computer/modular_shield/ui_interact(mob/user, datum/tgui/ui) + . = ..() + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "ModularShieldConsole") + ui.open() + +/obj/machinery/computer/modular_shield/ui_data(mob/user) + var/list/data = list() + var/list/generator_list = list() + for(var/i in 1 to LAZYLEN(generators)) + var/obj/machinery/modular_shield_generator/generator = generators[i] + var/list/this_generator = list() + this_generator["name"] = generator.display_name + this_generator["id"] = i + this_generator["max_strength"] = generator.max_strength + this_generator["current_strength"] = generator.stored_strength + this_generator["generator_name"] = generator.display_name + this_generator["active"] = generator.active + this_generator["recovering"] = generator.recovering || generator.initiating + this_generator["current_regeneration"] = generator.current_regeneration + if(generator.machine_stat & NOPOWER) + this_generator["inactive"] = TRUE + generator_list += list(this_generator) + data["generators"] = generator_list + return data + +/obj/machinery/computer/modular_shield/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) + . = ..() + if(.) + return + var/obj/machinery/modular_shield_generator/selected_generator = generators[(params["id"])] + if(QDELETED(selected_generator)) + return + switch(action) + if("toggle_shields") + selected_generator.toggle_shields() + return TRUE + if("rename") + selected_generator.display_name = params["name"] + return TRUE diff --git a/code/game/machinery/modular_shield.dm b/code/game/machinery/modular_shield.dm index 937a2a8fd9e..f121c9ff551 100644 --- a/code/game/machinery/modular_shield.dm +++ b/code/game/machinery/modular_shield.dm @@ -67,6 +67,9 @@ ///This is the lazy list of perimeter turfs that we grab when making large shields of 10 or more radius var/list/list_of_turfs + ///The name modular shield console tgui's see us as + var/display_name = "Shield Generator" + /obj/machinery/modular_shield_generator/power_change() . = ..() if(!(machine_stat & NOPOWER)) @@ -151,6 +154,11 @@ return ..() +/obj/machinery/modular_shield_generator/multitool_act(mob/living/user, obj/item/multitool/multi) + multi.set_buffer(src) + balloon_alert(user, "saved to buffer") + return ITEM_INTERACT_SUCCESS + ///toggles the forcefield on and off /obj/machinery/modular_shield_generator/proc/toggle_shields() if(initiating) diff --git a/code/game/objects/items/circuitboards/computer_circuitboards.dm b/code/game/objects/items/circuitboards/computer_circuitboards.dm index 044ff28b616..de00d37c3db 100644 --- a/code/game/objects/items/circuitboards/computer_circuitboards.dm +++ b/code/game/objects/items/circuitboards/computer_circuitboards.dm @@ -222,6 +222,11 @@ greyscale_colors = CIRCUIT_COLOR_ENGINEERING build_path = /obj/machinery/computer/message_monitor +/obj/item/circuitboard/computer/modular_shield_console + name = "Modular Shield Generator Console" + greyscale_colors = CIRCUIT_COLOR_ENGINEERING + build_path = /obj/machinery/computer/modular_shield + /obj/item/circuitboard/computer/powermonitor name = "Power Monitor" //name fixed 250810 greyscale_colors = CIRCUIT_COLOR_ENGINEERING diff --git a/code/modules/research/designs/machine_designs.dm b/code/modules/research/designs/machine_designs.dm index ddc9ad7c6dc..9b9da95936d 100644 --- a/code/modules/research/designs/machine_designs.dm +++ b/code/modules/research/designs/machine_designs.dm @@ -257,6 +257,16 @@ ) departmental_flags = DEPARTMENT_BITFLAG_ENGINEERING +/datum/design/board/modular_shield_console + name = "Modular Shield Console Board" + desc = "The circuit board for a modular shield console." + id = "modular_shield_console" + build_path = /obj/item/circuitboard/computer/modular_shield_console + category = list( + RND_CATEGORY_MACHINE + RND_SUBCATEGORY_MACHINE_ENGINEERING + ) + departmental_flags = DEPARTMENT_BITFLAG_ENGINEERING + /datum/design/board/teleconsole name = "Teleporter Console Board" desc = "Allows for the construction of circuit boards used to build a teleporter control console." diff --git a/code/modules/research/techweb/nodes/engi_nodes.dm b/code/modules/research/techweb/nodes/engi_nodes.dm index 6bb46920126..3a0da339d2b 100644 --- a/code/modules/research/techweb/nodes/engi_nodes.dm +++ b/code/modules/research/techweb/nodes/engi_nodes.dm @@ -225,6 +225,7 @@ "modular_shield_relay", "modular_shield_charger", "modular_shield_well", + "modular_shield_console", ) research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_2_POINTS) diff --git a/tgstation.dme b/tgstation.dme index 86fa61cde93..de5e786d44b 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -2217,6 +2217,7 @@ #include "code\game\machinery\computer\launchpad_control.dm" #include "code\game\machinery\computer\law.dm" #include "code\game\machinery\computer\mechlaunchpad.dm" +#include "code\game\machinery\computer\modular_shield.dm" #include "code\game\machinery\computer\operating_computer.dm" #include "code\game\machinery\computer\pod.dm" #include "code\game\machinery\computer\robot.dm" diff --git a/tgui/packages/tgui/interfaces/ModularShieldConsole.tsx b/tgui/packages/tgui/interfaces/ModularShieldConsole.tsx new file mode 100644 index 00000000000..66968025c28 --- /dev/null +++ b/tgui/packages/tgui/interfaces/ModularShieldConsole.tsx @@ -0,0 +1,128 @@ +import { + Button, + Input, + NoticeBox, + ProgressBar, + Section, + Table, +} from 'tgui-core/components'; +import { BooleanLike } from 'tgui-core/react'; + +import { useBackend } from '../backend'; +import { Window } from '../layouts'; + +type GeneratorStats = { + name: string; + id: number; + max_strength: number; + current_strength: number; + active: BooleanLike; + recovering: BooleanLike; + current_regeneration: number; +}; + +type Data = { + generators: GeneratorStats[]; +}; + +export const ModularShieldConsole = () => { + const { data } = useBackend(); + const { generators } = data; + return ( + + + {generators.length === 0 ? ( + No Generators Connected + ) : ( +
+ +
+ )} +
+
+ ); +}; + +const GeneratorTable = () => { + const { data } = useBackend(); + const { generators } = data; + return ( + + + Name + + Status + + + Toggle + + + {generators.map((stat) => ( + + ))} +
+ ); +}; + +type GeneratorTableEntryProps = { + GeneratorData: GeneratorStats; +}; + +const GeneratorTableEntry = (props: GeneratorTableEntryProps) => { + const { act, data } = useBackend(); + const { GeneratorData } = props; + const { + name, + id, + max_strength, + current_strength, + active, + recovering, + current_regeneration, + } = GeneratorData; + + return ( + + + + act('rename', { + id, + name: value, + }) + } + /> + + + + {current_strength}/{max_strength} + {current_regeneration} + + + +