From 02bb4637eb073be7befa4b442467036ebda31d60 Mon Sep 17 00:00:00 2001 From: ShadowLarkens Date: Tue, 18 Aug 2020 20:27:03 -0700 Subject: [PATCH] TGUI Point Defense Mainframe & Advanced Shield Generator --- code/game/machinery/pointdefense.dm | 47 ++-- code/modules/shieldgen/shield_generator.dm | 161 ++++++------- nano/templates/pointdefense_control.tmpl | 54 ----- nano/templates/shield_generator.tmpl | 158 ------------- .../tgui/interfaces/OvermapShieldGenerator.js | 212 ++++++++++++++++++ .../tgui/interfaces/PointDefenseControl.js | 47 ++++ .../tgui/interfaces/common/Overmap.js | 2 +- tgui/packages/tgui/public/tgui.bundle.js | 16 +- 8 files changed, 369 insertions(+), 328 deletions(-) delete mode 100644 nano/templates/pointdefense_control.tmpl delete mode 100644 nano/templates/shield_generator.tmpl create mode 100644 tgui/packages/tgui/interfaces/OvermapShieldGenerator.js create mode 100644 tgui/packages/tgui/interfaces/PointDefenseControl.js diff --git a/code/game/machinery/pointdefense.dm b/code/game/machinery/pointdefense.dm index f135bdd568..8eeb73fbc5 100644 --- a/code/game/machinery/pointdefense.dm +++ b/code/game/machinery/pointdefense.dm @@ -15,7 +15,6 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/power/pointdefense) anchored = TRUE circuit = /obj/item/weapon/circuitboard/pointdefense_control var/list/targets = list() // Targets being engaged by associated batteries - var/ui_template = "pointdefense_control.tmpl" var/id_tag = null /obj/machinery/pointdefense_control/Initialize(mapload) @@ -37,48 +36,42 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/power/pointdefense) if(!id_tag) . += "[desc_panel_image("multitool")]to set ident tag" -/obj/machinery/pointdefense_control/ui_interact(var/mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - if(ui_template) - var/list/data = build_ui_data() - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - ui = new(user, src, ui_key, ui_template, name, 400, 600) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) +/obj/machinery/pointdefense_control/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "PointDefenseControl") // 400, 600 + ui.open() /obj/machinery/pointdefense_control/attack_hand(mob/user) - if((. = ..())) - return - if(CanUseTopic(user, global.default_state) > STATUS_CLOSE) - ui_interact(user) + if(..()) + return TRUE + tgui_interact(user) + return TRUE + +/obj/machinery/pointdefense_control/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) + if(..()) return TRUE -/obj/machinery/pointdefense_control/Topic(var/mob/user, var/href_list) - if((. = ..())) - return - - if(href_list["toggle_active"]) - var/obj/machinery/power/pointdefense/PD = locate(href_list["toggle_active"]) + if(action == "toggle_active") + var/obj/machinery/power/pointdefense/PD = locate(params["target"]) if(!istype(PD)) - return TOPIC_NOACTION + return FALSE //if(!lan || !lan.is_connected(PD)) if(PD.id_tag != id_tag) - return TOPIC_NOACTION + return FALSE if(!(get_z(PD) in GetConnectedZlevels(get_z(src)))) - to_chat(user, "[PD] is not within control range.") - return TOPIC_NOACTION + to_chat(usr, "[PD] is not within control range.") + return FALSE if(!PD.Activate()) //Activate() whilst the device is active will return false. PD.Deactivate() - return TOPIC_REFRESH + return TRUE -/obj/machinery/pointdefense_control/proc/build_ui_data() +/obj/machinery/pointdefense_control/tgui_data(mob/user) var/list/data = list() data["id"] = id_tag - data["name"] = name var/list/turrets = list() if(id_tag) var/list/connected_z_levels = GetConnectedZlevels(get_z(src)) diff --git a/code/modules/shieldgen/shield_generator.dm b/code/modules/shieldgen/shield_generator.dm index 824eb86f66..cc3d2f1b25 100644 --- a/code/modules/shieldgen/shield_generator.dm +++ b/code/modules/shieldgen/shield_generator.dm @@ -400,8 +400,14 @@ spinup_counter = round(spinup_delay / idle_multiplier) update_icon() -/obj/machinery/power/shield_generator/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - var/data[0] +/obj/machinery/power/shield_generator/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "OvermapShieldGenerator", name) // 500, 800 + ui.open() + +/obj/machinery/power/shield_generator/tgui_data(mob/user) + var/list/data = list() data["running"] = running data["modes"] = get_flag_descriptions() @@ -427,12 +433,7 @@ data["idle_valid_values"] = idle_valid_values data["spinup_counter"] = spinup_counter - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - ui = new(user, src, ui_key, "shield_generator.tmpl", src.name, 500, 800) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) + return data /obj/machinery/power/shield_generator/attack_hand(mob/user) if((. = ..())) @@ -440,99 +441,99 @@ if(panel_open && Adjacent(user)) wires.Interact(user) return - if(CanUseTopic(user, global.default_state) > STATUS_CLOSE) - ui_interact(user) - return TRUE + tgui_interact(user) -/obj/machinery/power/shield_generator/CanUseTopic(var/mob/user) +/obj/machinery/power/shield_generator/tgui_status(mob/user) if(issilicon(user) && !Adjacent(user) && ai_control_disabled) return STATUS_UPDATE if(panel_open) return min(..(), STATUS_DISABLED) return ..() -/obj/machinery/power/shield_generator/Topic(href, href_list, datum/topic_state/state = default_state) - if((. = ..())) - return +/obj/machinery/power/shield_generator/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) + if(..()) + return TRUE - if(href_list["begin_shutdown"]) - if(running < SHIELD_RUNNING) // Discharging or off - return - var/alert = alert(usr, "Are you sure you wish to do this? It will drain the power inside the internal storage rapidly.", "Are you sure?", "Yes", "No") - if(!CanInteract(usr, state)) - return - if(running < SHIELD_RUNNING) - return - if(alert == "Yes") - set_idle(TRUE) // do this first to clear the field - running = SHIELD_DISCHARGING - return TOPIC_REFRESH + switch(action) + if("begin_shutdown") + if(running < SHIELD_RUNNING) // Discharging or off + return + var/alert = alert(usr, "Are you sure you wish to do this? It will drain the power inside the internal storage rapidly.", "Are you sure?", "Yes", "No") + if(tgui_status(usr, state) != STATUS_INTERACTIVE) + return + if(running < SHIELD_RUNNING) + return + if(alert == "Yes") + set_idle(TRUE) // do this first to clear the field + running = SHIELD_DISCHARGING + return TRUE - if(href_list["start_generator"]) - if(offline_for) - return - set_idle(TRUE) - return TOPIC_REFRESH + if("start_generator") + if(offline_for) + return + set_idle(TRUE) + return TRUE - if(href_list["toggle_idle"]) - if(running < SHIELD_RUNNING) - return TOPIC_HANDLED - set_idle(text2num(href_list["toggle_idle"])) - return TOPIC_REFRESH + if("toggle_idle") + if(running < SHIELD_RUNNING) + return TRUE + set_idle(text2num(params["toggle_idle"])) + return TRUE - // Instantly drops the shield, but causes a cooldown before it may be started again. Also carries a risk of EMP at high charge. - if(href_list["emergency_shutdown"]) - if(!running) - return TOPIC_HANDLED + // Instantly drops the shield, but causes a cooldown before it may be started again. Also carries a risk of EMP at high charge. + if("emergency_shutdown") + if(!running) + return TRUE - var/choice = input(usr, "Are you sure that you want to initiate an emergency shield shutdown? This will instantly drop the shield, and may result in unstable release of stored electromagnetic energy. Proceed at your own risk.") in list("Yes", "No") - if((choice != "Yes") || !running) - return TOPIC_HANDLED + var/choice = input(usr, "Are you sure that you want to initiate an emergency shield shutdown? This will instantly drop the shield, and may result in unstable release of stored electromagnetic energy. Proceed at your own risk.") in list("Yes", "No") + if((choice != "Yes") || !running) + return TRUE - // If the shield would take 5 minutes to disperse and shut down using regular methods, it will take x1.5 (7 minutes and 30 seconds) of this time to cool down after emergency shutdown - offline_for = round(current_energy / (SHIELD_SHUTDOWN_DISPERSION_RATE / 1.5)) - var/old_energy = current_energy - shutdown_field() - log_and_message_admins("has triggered \the [src]'s emergency shutdown!", usr) - spawn() - empulse(src, old_energy / 60000000, old_energy / 32000000, 1) // If shields are charged at 450 MJ, the EMP will be 7.5, 14.0625. 90 MJ, 1.5, 2.8125 - old_energy = 0 + // If the shield would take 5 minutes to disperse and shut down using regular methods, it will take x1.5 (7 minutes and 30 seconds) of this time to cool down after emergency shutdown + offline_for = round(current_energy / (SHIELD_SHUTDOWN_DISPERSION_RATE / 1.5)) + var/old_energy = current_energy + shutdown_field() + log_and_message_admins("has triggered \the [src]'s emergency shutdown!", usr) + spawn() + empulse(src, old_energy / 60000000, old_energy / 32000000, 1) // If shields are charged at 450 MJ, the EMP will be 7.5, 14.0625. 90 MJ, 1.5, 2.8125 + old_energy = 0 - return TOPIC_REFRESH + return TRUE if(mode_changes_locked) - return TOPIC_REFRESH + return TRUE - if(href_list["set_range"]) - var/new_range = input(usr, "Enter new field range (1-[world.maxx]). Leave blank to cancel.", "Field Radius Control", field_radius) as num - if(!new_range) - return TOPIC_HANDLED - target_radius = between(1, new_range, world.maxx) - return TOPIC_REFRESH + switch(action) + if("set_range") + var/new_range = input(usr, "Enter new field range (1-[world.maxx]). Leave blank to cancel.", "Field Radius Control", field_radius) as num + if(!new_range) + return TRUE + target_radius = between(1, new_range, world.maxx) + return TRUE - if(href_list["set_input_cap"]) - var/new_cap = round(input(usr, "Enter new input cap (in kW). Enter 0 or nothing to disable input cap.", "Generator Power Control", round(input_cap / 1000)) as num) - if(!new_cap) - input_cap = 0 - return - input_cap = max(0, new_cap) * 1000 - return TOPIC_REFRESH + if("set_input_cap") + var/new_cap = round(input(usr, "Enter new input cap (in kW). Enter 0 or nothing to disable input cap.", "Generator Power Control", round(input_cap / 1000)) as num) + if(!new_cap) + input_cap = 0 + return + input_cap = max(0, new_cap) * 1000 + return TRUE - if(href_list["toggle_mode"]) - // Toggling hacked-only modes requires the hacked var to be set to 1 - if((text2num(href_list["toggle_mode"]) & (MODEFLAG_BYPASS | MODEFLAG_OVERCHARGE)) && !hacked) - return TOPIC_HANDLED + if("toggle_mode") + // Toggling hacked-only modes requires the hacked var to be set to 1 + if((text2num(params["toggle_mode"]) & (MODEFLAG_BYPASS | MODEFLAG_OVERCHARGE)) && !hacked) + return TRUE - toggle_flag(text2num(href_list["toggle_mode"])) - return TOPIC_REFRESH + toggle_flag(text2num(params["toggle_mode"])) + return TRUE - if(href_list["switch_idle"]) - if(running == SHIELD_SPINNING_UP) - return TOPIC_REFRESH - var/new_idle = text2num(href_list["switch_idle"]) - if(new_idle in idle_valid_values) - idle_multiplier = new_idle - return TOPIC_REFRESH + if("switch_idle") + if(running == SHIELD_SPINNING_UP) + return TRUE + var/new_idle = text2num(params["switch_idle"]) + if(new_idle in idle_valid_values) + idle_multiplier = new_idle + return TRUE /obj/machinery/power/shield_generator/proc/field_integrity() if(full_shield_strength) diff --git a/nano/templates/pointdefense_control.tmpl b/nano/templates/pointdefense_control.tmpl deleted file mode 100644 index 19f85d3dba..0000000000 --- a/nano/templates/pointdefense_control.tmpl +++ /dev/null @@ -1,54 +0,0 @@ -

Fire Assist Mainframe: {{:data.id || "[no tag]"}}

-{{if !(data.id)}} -
- This system has not been assigned an ident tag. Please contact your system administrator or conduct a manual update with a standard multitool. -
- {{/if}} -{{for data.turrets}} -

{{:value.id}}

-
-
- Battery status -
-
- {{if value.active}} - Online {{:helper.link('Shut down', null, {'toggle_active': value.ref})}} - {{else}} - Offline {{:helper.link('Start up', null, {'toggle_active': value.ref})}} - {{/if}} -
-
-
-
- Effective range -
-
- {{:value.effective_range}} -
-
-
-
- Reaction wheel delay -
-
- {{:value.reaction_wheel_delay}} -
-
-
-
- Recharge time -
-
- {{:value.recharge_time}} -
-{{empty}} -
-
- Error: -
-
- No weapon systems detected. Please check network connection. -
-
-
-{{/for}} diff --git a/nano/templates/shield_generator.tmpl b/nano/templates/shield_generator.tmpl deleted file mode 100644 index b93ddc6220..0000000000 --- a/nano/templates/shield_generator.tmpl +++ /dev/null @@ -1,158 +0,0 @@ -{{if data.offline_for}} -

EMERGENCY SHUTDOWN

- An emergency shutdown has been initiated - generator cooling down
- Please wait until the generator cools down before resuming operation. Estimated time left: {{:data.offline_for}} seconds. -{{else}} -

SYSTEM STATUS

-
-
- Generator is: -
-
- {{if data.running == 2}} - {{if data.overloaded}} - Recovering - {{else}} - Active - {{/if}} - {{else data.running == 1}} - Shutting Down - {{else data.running == 3}} - Inactive - {{else data.running == 4}} - Spinning Up  - {{if data.target_radius != data.field_radius}} - (Adjusting Radius) - {{else}} - ({{:data.spinup_counter * 2}}s) - {{/if}} - {{else}} - Offline - {{/if}} -
-
-
-
- Energy Storage: -
-
- {{:data.current_energy}}/{{:data.max_energy}} MJ ({{:data.percentage_energy}}%) -
-
-
-
- Shield Integrity: -
-
- {{:data.field_integrity}}% -
-
-
-
- Mitigation: -
-
- {{:data.mitigation_em}}% EM / {{:data.mitigation_physical}}% PH / {{:data.mitigation_heat}}% HE / {{:data.mitigation_max}}% MAX -
-
-
-
- Upkeep Energy Use: -
-
- {{:data.upkeep_power_usage}} kW -
-
-
-
- Total Energy Use: -
-
- {{if data.input_cap_kw}} - {{:data.power_usage}} / {{:data.input_cap_kw}} kW - {{else}} - {{:data.power_usage}} kW (No Limit) - {{/if}} -
-
-
-
- Field Size: -
-
- {{:data.functional_segments}} / {{:data.total_segments}} m2 (radius {{:data.field_radius}}, target {{:data.target_radius}}) -
-
-

CONTROLS

- - - {{if (data.running >= 2)}} - - {{else}} - - {{/if}} - {{else}} - - - - -
{{:helper.link('Turn off', null, {'begin_shutdown' : '1'})}} - {{if (data.running == 3)}} - {{:helper.link('Activate', null, {'toggle_idle' : '0'})}} {{:helper.link('Deactivate', null, {'toggle_idle' : '1'})}} {{:helper.link('Turn on', null, {'start_generator' : '1'})}} - {{/if}} - {{if data.running}} - {{if data.hacked}} - {{:helper.link('EMERGENCY SHUTDOWN', null, {'emergency_shutdown' : '1'}, null, 'redButton')}} - {{/if}} - {{/if}} - -
{{:helper.link('Set Field Range', null, {'set_range' : '1'})}} - {{:helper.link('Set Input Cap', null, {'set_input_cap' : '1'})}} -
Set inactive power use intensity: - {{for data.idle_valid_values}} - {{:helper.link(value, null, {'switch_idle' : value}, (value == data.idle_multiplier) ? 'selected' : (data.running == 4 ? 'disabled' : null))}} - {{/for}} -
-

FIELD CALIBRATION

-
- {{for data.modes}} -
-
- Mode: -
-
- {{:value.name}} -
-
-
-
- Description: -
-
- {{:value.desc}} -
-
-
-
- Status: -
-
- {{if value.status}} - Enabled - {{else}} - Disabled - {{/if}} - {{:helper.link('Toggle', null, {'toggle_mode' : value.flag})}} -
-
-
-
- Multiplier: -
-
- {{:value.multiplier}} -
-
-
- {{/for}} -{{/if}} \ No newline at end of file diff --git a/tgui/packages/tgui/interfaces/OvermapShieldGenerator.js b/tgui/packages/tgui/interfaces/OvermapShieldGenerator.js new file mode 100644 index 0000000000..11236f8ab0 --- /dev/null +++ b/tgui/packages/tgui/interfaces/OvermapShieldGenerator.js @@ -0,0 +1,212 @@ +import { round } from 'common/math'; +import { Fragment } from 'inferno'; +import { useBackend, useLocalState } from "../backend"; +import { Box, Button, Flex, Icon, LabeledList, ProgressBar, Section, Table, AnimatedNumber } from "../components"; +import { Window } from "../layouts"; + +export const OvermapShieldGenerator = (props, context) => { + return ( + + + + + + ); +}; + +const OvermapShieldGeneratorContent = (props, context) => { + const { act, data } = useBackend(context); + const { + modes, + offline_for, + } = data; + + if (offline_for) { + return ( +
+ An emergency shutdown has been initiated - generator cooling down. + Please wait until the generator cools down before resuming operation. + Estimated time left: {offline_for} seconds. +
+ ); + } + + return ( + + + +
+ {modes.map(mode => ( +
act("toggle_mode", { toggle_mode: mode.flag })}> + {mode.status ? "Enabled" : "Disabled"} + + }> + + {mode.desc} + + + Multiplier: {mode.multiplier} + +
+ ))} +
+
+ ); +}; + +const OvermapShieldGeneratorStatus = (props, context) => { + const { act, data } = useBackend(context); + const { + running, + overloaded, + mitigation_max, + mitigation_physical, + mitigation_em, + mitigation_heat, + field_integrity, + max_energy, + current_energy, + percentage_energy, + total_segments, + functional_segments, + field_radius, + target_radius, + input_cap_kw, + upkeep_power_usage, + power_usage, + spinup_counter, + } = data; + + return ( +
+ + + {running === 1 && ( + Shutting Down + ) || running === 2 && ( + overloaded && ( + Overloaded + ) || ( + Running + ) + ) || running === 3 && ( + Inactive + ) || running === 4 && ( + + Spinning Up  + {target_radius !== field_radius && ( + (Adjusting Radius) + ) || ( + {spinup_counter * 2}s + )} + + ) || ( + + Offline + + )} + + + + {current_energy} / {max_energy} MJ ({percentage_energy}%) + + + + % + + + {mitigation_em}% EM / {mitigation_physical}% PH / {mitigation_heat}% HE / {mitigation_max}% MAX + + + kW + + + {input_cap_kw && ( + + + {power_usage} / {input_cap_kw} kW + + + ) || ( + + kW (No Limit) + + )} + + +  /  + m² + (radius , target ) + + +
+ ); +}; + +const OvermapShieldGeneratorControls = (props, context) => { + const { act, data } = useBackend(context); + const { + running, + hacked, + idle_multiplier, + idle_valid_values, + } = data; + + return ( +
+ {running >= 2 && ( + + + {running === 3 && ( + + ) || ( + + )} + + ) || ( + + )} + {running && hacked && ( + + ) || null} + + }> + + + + + {idle_valid_values.map(val => ( + + ))} + + +
+ ); +}; \ No newline at end of file diff --git a/tgui/packages/tgui/interfaces/PointDefenseControl.js b/tgui/packages/tgui/interfaces/PointDefenseControl.js new file mode 100644 index 0000000000..68bcd56d55 --- /dev/null +++ b/tgui/packages/tgui/interfaces/PointDefenseControl.js @@ -0,0 +1,47 @@ +import { round } from 'common/math'; +import { Fragment } from 'inferno'; +import { useBackend, useLocalState } from "../backend"; +import { Box, Button, Flex, Icon, LabeledList, ProgressBar, Section, Table, AnimatedNumber } from "../components"; +import { Window } from "../layouts"; + +export const PointDefenseControl = (props, context) => { + const { act, data } = useBackend(context); + const { + id, + turrets, + } = data; + return ( + + +
+ {turrets.length && turrets.map(pd => ( +
act("toggle_active", { target: pd.ref })}> + {pd.active ? "Online" : "Offline"} + + }> + + + {pd.effective_range} + + + {pd.reaction_wheel_delay} + + + {pd.recharge_time} + + +
+ )) || ( + + Error: No weapon systems detected. Please check network connection. + + )} +
+
+
+ ); +}; \ No newline at end of file diff --git a/tgui/packages/tgui/interfaces/common/Overmap.js b/tgui/packages/tgui/interfaces/common/Overmap.js index 17a2b2cfee..bc0af18f93 100644 --- a/tgui/packages/tgui/interfaces/common/Overmap.js +++ b/tgui/packages/tgui/interfaces/common/Overmap.js @@ -96,7 +96,7 @@ export const OvermapPanControls = (props, context) => {