mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-10 18:22:39 +00:00
[MIRROR] Replace most legacy robot interfaces with a unified interface (#9323)
Co-authored-by: ShadowLarkens <shadowlarkens@gmail.com>
This commit is contained in:
committed by
GitHub
parent
a1a4071f70
commit
c85c19567e
@@ -158,6 +158,7 @@
|
||||
return 0
|
||||
|
||||
R.emag_items = 1
|
||||
R.robotact.update_static_data_for_all_viewers()
|
||||
return 1
|
||||
|
||||
/obj/item/borg/upgrade/basic/language
|
||||
|
||||
@@ -18,13 +18,11 @@
|
||||
set hidden = 1
|
||||
toggle_module(module)
|
||||
|
||||
/mob/living/silicon/robot/proc/uneq_active()
|
||||
if(isnull(module_active))
|
||||
/mob/living/silicon/robot/proc/uneq_specific(obj/item/I)
|
||||
if(!istype(I))
|
||||
return
|
||||
var/obj/item/I = module_active
|
||||
for(var/datum/action/A as anything in I.actions)
|
||||
A.Remove(src)
|
||||
if(module_state_1 == module_active)
|
||||
|
||||
if(module_state_1 == I)
|
||||
if(istype(module_state_1,/obj/item/borg/sight))
|
||||
sight_mode &= ~module_state_1:sight_mode
|
||||
if (client)
|
||||
@@ -34,30 +32,46 @@
|
||||
module_state_1:loc = module //So it can be used again later
|
||||
module_state_1 = null
|
||||
inv1.icon_state = "inv1"
|
||||
else if(module_state_2 == module_active)
|
||||
else if(module_state_2 == I)
|
||||
if(istype(module_state_2,/obj/item/borg/sight))
|
||||
sight_mode &= ~module_state_2:sight_mode
|
||||
if (client)
|
||||
client.screen -= module_state_2
|
||||
contents -= module_state_2
|
||||
module_active = null
|
||||
module_state_2:loc = module
|
||||
module_state_2:loc = module //So it can be used again later
|
||||
module_state_2 = null
|
||||
inv2.icon_state = "inv2"
|
||||
else if(module_state_3 == module_active)
|
||||
else if(module_state_3 == I)
|
||||
if(istype(module_state_3,/obj/item/borg/sight))
|
||||
sight_mode &= ~module_state_3:sight_mode
|
||||
if (client)
|
||||
client.screen -= module_state_3
|
||||
contents -= module_state_3
|
||||
module_active = null
|
||||
module_state_3:loc = module
|
||||
module_state_3:loc = module //So it can be used again later
|
||||
module_state_3 = null
|
||||
inv3.icon_state = "inv3"
|
||||
else
|
||||
return
|
||||
|
||||
for(var/datum/action/A as anything in I.actions)
|
||||
A.Remove(src)
|
||||
|
||||
after_equip()
|
||||
update_icon()
|
||||
hud_used.update_robot_modules_display()
|
||||
|
||||
/mob/living/silicon/robot/proc/uneq_active()
|
||||
if(isnull(module_active))
|
||||
return
|
||||
|
||||
var/obj/item/I = module_active
|
||||
for(var/datum/action/A as anything in I.actions)
|
||||
A.Remove(src)
|
||||
|
||||
uneq_specific(I)
|
||||
|
||||
/mob/living/silicon/robot/proc/uneq_all()
|
||||
module_active = null
|
||||
|
||||
@@ -100,6 +114,17 @@
|
||||
after_equip()
|
||||
update_icon()
|
||||
|
||||
// Just used for pretty display in TGUI
|
||||
/mob/living/silicon/robot/proc/get_slot_from_module(obj/item/I)
|
||||
if(module_state_1 == I)
|
||||
return 1
|
||||
else if(module_state_2 == I)
|
||||
return 2
|
||||
else if(module_state_3 == I)
|
||||
return 3
|
||||
else
|
||||
return 0
|
||||
|
||||
/mob/living/silicon/robot/proc/activated(obj/item/O)
|
||||
if(module_state_1 == O)
|
||||
return 1
|
||||
|
||||
@@ -135,6 +135,7 @@
|
||||
spark_system = new /datum/effect/effect/system/spark_spread()
|
||||
spark_system.set_up(5, 0, src)
|
||||
spark_system.attach(src)
|
||||
robotact = new(src)
|
||||
|
||||
add_language("Robot Talk", 1)
|
||||
add_language(LANGUAGE_GALCOM, 1)
|
||||
@@ -318,6 +319,7 @@
|
||||
revert_shell() // To get it out of the GLOB list.
|
||||
qdel(wires)
|
||||
wires = null
|
||||
QDEL_NULL(robotact)
|
||||
return ..()
|
||||
|
||||
// CONTINUE CODING HERE
|
||||
@@ -379,6 +381,7 @@
|
||||
updatename()
|
||||
hud_used.update_robot_modules_display()
|
||||
notify_ai(ROBOT_NOTIFICATION_NEW_MODULE, module.name)
|
||||
robotact?.update_static_data_for_all_viewers()
|
||||
|
||||
/mob/living/silicon/robot/proc/update_braintype()
|
||||
if(istype(mmi, /obj/item/mmi/digital/posibrain))
|
||||
@@ -465,17 +468,6 @@
|
||||
|
||||
sprite_datum.handle_extra_customization(src)
|
||||
|
||||
/mob/living/silicon/robot/proc/self_diagnosis()
|
||||
if(!is_component_functioning("diagnosis unit"))
|
||||
return null
|
||||
|
||||
var/dat = "<HEAD><TITLE>[src.name] Self-Diagnosis Report</TITLE></HEAD><BODY>\n"
|
||||
for (var/V in components)
|
||||
var/datum/robot_component/C = components[V]
|
||||
dat += span_bold("[C.name]") + "<br><table><tr><td>Brute Damage:</td><td>[C.brute_damage]</td></tr><tr><td>Electronics Damage:</td><td>[C.electronics_damage]</td></tr><tr><td>Powered:</td><td>[(!C.idle_usage || C.is_powered()) ? "Yes" : "No"]</td></tr><tr><td>Toggled:</td><td>[ C.toggled ? "Yes" : "No"]</td></table><br>"
|
||||
|
||||
return dat
|
||||
|
||||
/mob/living/silicon/robot/verb/toggle_lights()
|
||||
set category = "Abilities.Silicon"
|
||||
set name = "Toggle Lights"
|
||||
@@ -485,44 +477,6 @@
|
||||
handle_light()
|
||||
update_icon()
|
||||
|
||||
/mob/living/silicon/robot/verb/self_diagnosis_verb()
|
||||
set category = "Abilities.Silicon"
|
||||
set name = "Self Diagnosis"
|
||||
|
||||
if(!is_component_functioning("diagnosis unit"))
|
||||
to_chat(src, span_red("Your self-diagnosis component isn't functioning."))
|
||||
|
||||
var/datum/robot_component/CO = get_component("diagnosis unit")
|
||||
if (!cell_use_power(CO.active_usage))
|
||||
to_chat(src, span_red("Low Power."))
|
||||
var/dat = self_diagnosis()
|
||||
src << browse(dat, "window=robotdiagnosis")
|
||||
|
||||
|
||||
/mob/living/silicon/robot/verb/toggle_component()
|
||||
set category = "Abilities.Silicon"
|
||||
set name = "Toggle Component"
|
||||
set desc = "Toggle a component, conserving power."
|
||||
|
||||
var/list/installed_components = list()
|
||||
for(var/V in components)
|
||||
if(V == "power cell") continue
|
||||
var/datum/robot_component/C = components[V]
|
||||
if(C.installed)
|
||||
installed_components += V
|
||||
|
||||
var/toggle = tgui_input_list(src, "Which component do you want to toggle?", "Toggle Component", installed_components)
|
||||
if(!toggle)
|
||||
return
|
||||
|
||||
var/datum/robot_component/C = components[toggle]
|
||||
if(C.toggled)
|
||||
C.toggled = 0
|
||||
to_chat(src, span_red("You disable [C.name]."))
|
||||
else
|
||||
C.toggled = 1
|
||||
to_chat(src, span_red("You enable [C.name]."))
|
||||
|
||||
/mob/living/silicon/robot/verb/spark_plug() //So you can still sparkle on demand without violence.
|
||||
set category = "Abilities.Silicon"
|
||||
set name = "Emit Sparks"
|
||||
@@ -858,6 +812,7 @@
|
||||
module = null
|
||||
updatename("Default")
|
||||
has_recoloured = FALSE
|
||||
robotact?.update_static_data_for_all_viewers()
|
||||
|
||||
/mob/living/silicon/robot/proc/ColorMate()
|
||||
set name = "Recolour Module"
|
||||
@@ -1101,42 +1056,7 @@
|
||||
add_overlay(open_overlay)
|
||||
|
||||
/mob/living/silicon/robot/proc/installed_modules()
|
||||
if(weapon_lock)
|
||||
to_chat(src, span_filter_warning("" + span_red("Weapon lock active, unable to use modules! Count:[weaponlock_time]") + ""))
|
||||
return
|
||||
|
||||
if(!module)
|
||||
pick_module()
|
||||
return
|
||||
var/dat = "<HEAD><TITLE>Modules</TITLE></HEAD><BODY>\n"
|
||||
dat += {"
|
||||
<B>Activated Modules</B>
|
||||
<BR>
|
||||
Module 1: [module_state_1 ? "<A HREF=?src=\ref[src];mod=\ref[module_state_1]>[module_state_1]<A>" : "No Module"]<BR>
|
||||
Module 2: [module_state_2 ? "<A HREF=?src=\ref[src];mod=\ref[module_state_2]>[module_state_2]<A>" : "No Module"]<BR>
|
||||
Module 3: [module_state_3 ? "<A HREF=?src=\ref[src];mod=\ref[module_state_3]>[module_state_3]<A>" : "No Module"]<BR>
|
||||
<BR>
|
||||
<B>Installed Modules</B><BR><BR>"}
|
||||
|
||||
|
||||
for (var/obj in module.modules)
|
||||
if (!obj)
|
||||
dat += span_bold("Resource depleted") + "<BR>"
|
||||
else if(activated(obj))
|
||||
dat += text("[obj]: <B>Activated</B><BR>")
|
||||
else
|
||||
dat += text("[obj]: <A HREF=?src=\ref[src];act=\ref[obj]>Activate</A><BR>")
|
||||
if (emagged || emag_items)
|
||||
for (var/obj in module.emag)
|
||||
if (!obj)
|
||||
dat += span_bold("Resource depleted") + "<BR>"
|
||||
else if(activated(obj))
|
||||
dat += text("[obj]: <B>Activated</B><BR>")
|
||||
else
|
||||
dat += text("[obj]: <A HREF=?src=\ref[src];act=\ref[obj]>Activate</A><BR>")
|
||||
|
||||
src << browse(dat, "window=robotmod")
|
||||
|
||||
robotact.tgui_interact(src)
|
||||
|
||||
/mob/living/silicon/robot/Topic(href, href_list)
|
||||
if(..())
|
||||
@@ -1150,69 +1070,6 @@
|
||||
subsystem_alarm_monitor()
|
||||
return 1
|
||||
|
||||
if (href_list["mod"])
|
||||
var/obj/item/O = locate(href_list["mod"])
|
||||
if (istype(O) && (O.loc == src))
|
||||
O.attack_self(src)
|
||||
return 1
|
||||
|
||||
if (href_list["act"])
|
||||
var/obj/item/O = locate(href_list["act"])
|
||||
if (!istype(O))
|
||||
return 1
|
||||
|
||||
if(!((O in src.module.modules) || (O in src.module.emag)))
|
||||
return 1
|
||||
|
||||
if(activated(O))
|
||||
to_chat(src, span_filter_notice("Already activated."))
|
||||
return 1
|
||||
if(!module_state_1)
|
||||
module_state_1 = O
|
||||
O.hud_layerise()
|
||||
O.equipped_robot()
|
||||
contents += O
|
||||
if(istype(module_state_1,/obj/item/borg/sight))
|
||||
sight_mode |= module_state_1:sight_mode
|
||||
else if(!module_state_2)
|
||||
module_state_2 = O
|
||||
O.hud_layerise()
|
||||
O.equipped_robot()
|
||||
contents += O
|
||||
if(istype(module_state_2,/obj/item/borg/sight))
|
||||
sight_mode |= module_state_2:sight_mode
|
||||
else if(!module_state_3)
|
||||
module_state_3 = O
|
||||
O.hud_layerise()
|
||||
O.equipped_robot()
|
||||
contents += O
|
||||
if(istype(module_state_3,/obj/item/borg/sight))
|
||||
sight_mode |= module_state_3:sight_mode
|
||||
else
|
||||
to_chat(src, span_filter_notice("You need to disable a module first!"))
|
||||
installed_modules()
|
||||
return 1
|
||||
|
||||
if (href_list["deact"])
|
||||
var/obj/item/O = locate(href_list["deact"])
|
||||
if(activated(O))
|
||||
if(module_state_1 == O)
|
||||
module_state_1 = null
|
||||
contents -= O
|
||||
else if(module_state_2 == O)
|
||||
module_state_2 = null
|
||||
contents -= O
|
||||
else if(module_state_3 == O)
|
||||
module_state_3 = null
|
||||
contents -= O
|
||||
else
|
||||
to_chat(src, span_filter_notice("Module isn't activated."))
|
||||
else
|
||||
to_chat(src, span_filter_notice("Module isn't activated."))
|
||||
installed_modules()
|
||||
return 1
|
||||
return
|
||||
|
||||
/mob/living/silicon/robot/proc/radio_menu()
|
||||
radio.interact(src)//Just use the radio's Topic() instead of bullshit special-snowflake code
|
||||
|
||||
@@ -1492,6 +1349,7 @@
|
||||
sleep(6)
|
||||
if(prob(50))
|
||||
emagged = 1
|
||||
robotact.update_static_data_for_all_viewers()
|
||||
lawupdate = 0
|
||||
disconnect_from_ai()
|
||||
to_chat(user, span_filter_notice("You emag [src]'s interface."))
|
||||
@@ -1783,3 +1641,12 @@
|
||||
return (has_basic_upgrade(given_type) || has_advanced_upgrade(given_type) || has_restricted_upgrade(given_type) || has_no_prod_upgrade(given_type))
|
||||
|
||||
#undef CYBORG_POWER_USAGE_MULTIPLIER
|
||||
|
||||
/mob/living/silicon/robot/vv_edit_var(var_name, var_value)
|
||||
switch(var_name)
|
||||
if(NAMEOF(src, emagged))
|
||||
robotact?.update_static_data_for_all_viewers()
|
||||
if(NAMEOF(src, emag_items))
|
||||
robotact?.update_static_data_for_all_viewers()
|
||||
|
||||
. = ..()
|
||||
|
||||
180
code/modules/mob/living/silicon/robot/robot_ui.dm
Normal file
180
code/modules/mob/living/silicon/robot/robot_ui.dm
Normal file
@@ -0,0 +1,180 @@
|
||||
/mob/living/silicon/robot
|
||||
var/datum/tgui_module/robot_ui/robotact
|
||||
|
||||
// Major Control UI for all things robots can do.
|
||||
/datum/tgui_module/robot_ui
|
||||
name = "Robotact"
|
||||
tgui_id = "Robotact"
|
||||
|
||||
/datum/tgui_module/robot_ui/tgui_state(mob/user)
|
||||
return GLOB.tgui_self_state
|
||||
|
||||
/datum/tgui_module/robot_ui/tgui_static_data()
|
||||
var/list/data = ..()
|
||||
|
||||
var/mob/living/silicon/robot/R = host
|
||||
|
||||
if(!R.module)
|
||||
return data
|
||||
|
||||
var/list/modules = list()
|
||||
for(var/obj/item/I as anything in R.module.modules)
|
||||
if(!I)
|
||||
continue
|
||||
|
||||
UNTYPED_LIST_ADD(modules, list(
|
||||
"ref" = REF(I),
|
||||
"name" = "[I]",
|
||||
"icon" = "[I.icon]",
|
||||
"icon_state" = "[I.icon_state]",
|
||||
))
|
||||
data["modules_static"] = modules
|
||||
|
||||
var/list/emag_modules = list()
|
||||
if(R.emagged || R.emag_items)
|
||||
for(var/obj/item/I as anything in R.module.emag)
|
||||
if(!I)
|
||||
continue
|
||||
|
||||
UNTYPED_LIST_ADD(emag_modules, list(
|
||||
"ref" = REF(I),
|
||||
"name" = "[I.name]",
|
||||
"icon" = "[I.icon]",
|
||||
"icon_state" = "[I.icon_state]",
|
||||
))
|
||||
data["emag_modules_static"] = emag_modules
|
||||
|
||||
return data
|
||||
|
||||
/datum/tgui_module/robot_ui/tgui_data()
|
||||
var/list/data = ..()
|
||||
|
||||
var/mob/living/silicon/robot/R = host
|
||||
|
||||
data["module_name"] = R.module ? "[R.module]" : null
|
||||
|
||||
if(!R.module)
|
||||
return data
|
||||
|
||||
data["name"] = R.name
|
||||
data["ai"] = "[R.connected_ai]"
|
||||
data["charge"] = R.cell?.charge
|
||||
data["max_charge"] = R.cell?.maxcharge
|
||||
data["health"] = R.health
|
||||
data["max_health"] = R.getMaxHealth()
|
||||
|
||||
data["weapon_lock"] = R.weapon_lock
|
||||
|
||||
var/list/modules = list()
|
||||
for(var/obj/item/I as anything in R.module.modules)
|
||||
if(!I)
|
||||
continue
|
||||
|
||||
LAZYSET(modules, REF(I), R.get_slot_from_module(I))
|
||||
data["modules"] = modules
|
||||
|
||||
var/list/emag_modules = list()
|
||||
if(R.emagged || R.emag_items)
|
||||
for(var/obj/item/I as anything in R.module.emag)
|
||||
if(!I)
|
||||
continue
|
||||
|
||||
LAZYSET(emag_modules, REF(I), R.get_slot_from_module(I))
|
||||
data["emag_modules"] = emag_modules
|
||||
|
||||
var/diagnosis_functional = R.is_component_functioning("diagnosis unit")
|
||||
data["diag_functional"] = diagnosis_functional
|
||||
|
||||
var/list/components = list()
|
||||
for(var/V in R.components)
|
||||
var/datum/robot_component/comp = R.components[V]
|
||||
|
||||
UNTYPED_LIST_ADD(components, list(
|
||||
"key" = V,
|
||||
"name" = "[comp]",
|
||||
"brute_damage" = comp.brute_damage,
|
||||
"electronics_damage" = diagnosis_functional ? comp.electronics_damage : -1,
|
||||
"max_damage" = diagnosis_functional ? comp.max_damage : -1,
|
||||
"idle_usage" = diagnosis_functional ? comp.idle_usage : -1,
|
||||
"is_powered" = diagnosis_functional ? comp.is_powered() : 0,
|
||||
"toggled" = comp.toggled,
|
||||
))
|
||||
data["components"] = components
|
||||
|
||||
return data
|
||||
|
||||
/datum/tgui_module/robot_ui/tgui_act(action, params)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
var/mob/living/silicon/robot/R = host
|
||||
|
||||
switch(action)
|
||||
if("select_module")
|
||||
R.pick_module()
|
||||
. = TRUE
|
||||
if("toggle_component")
|
||||
var/component = params["component"]
|
||||
var/datum/robot_component/C = LAZYACCESS(R.components, component)
|
||||
if(istype(C))
|
||||
C.toggled = !C.toggled
|
||||
if(C.toggled)
|
||||
to_chat(usr, span_notice("You enable [C]."))
|
||||
else
|
||||
to_chat(usr, span_warning("You disable [C]."))
|
||||
. = TRUE
|
||||
if("toggle_module")
|
||||
if(R.weapon_lock)
|
||||
to_chat(usr, span_danger("Error: Modules locked."))
|
||||
return
|
||||
var/obj/item/module = locate(params["ref"])
|
||||
if(istype(module))
|
||||
if(R.activated(module))
|
||||
R.uneq_specific(module)
|
||||
else
|
||||
R.activate_module(module)
|
||||
. = TRUE
|
||||
if("activate_module")
|
||||
var/obj/item/module = locate(params["ref"])
|
||||
if(istype(module) && module.loc == R)
|
||||
module.attack_self(R)
|
||||
. = TRUE
|
||||
|
||||
// Quick actions
|
||||
if("quick_action_comm")
|
||||
R.communicator?.attack_self(R)
|
||||
. = TRUE
|
||||
if("quick_action_pda")
|
||||
R.rbPDA?.tgui_interact(R)
|
||||
. = TRUE
|
||||
if("quick_action_crew_manifest")
|
||||
R.subsystem_crew_manifest()
|
||||
. = TRUE
|
||||
if("quick_action_law_manager")
|
||||
R.subsystem_law_manager()
|
||||
. = TRUE
|
||||
if("quick_action_alarm_monitoring")
|
||||
R.subsystem_alarm_monitor()
|
||||
. = TRUE
|
||||
if("quick_action_power_monitoring")
|
||||
R.subsystem_power_monitor()
|
||||
. = TRUE
|
||||
if("quick_action_take_image")
|
||||
R.take_image()
|
||||
. = TRUE
|
||||
if("quick_action_view_images")
|
||||
R.view_images()
|
||||
. = TRUE
|
||||
if("quick_action_delete_images")
|
||||
R.delete_images()
|
||||
. = TRUE
|
||||
if("quick_action_flashlight")
|
||||
R.toggle_lights()
|
||||
. = TRUE
|
||||
if("quick_action_sensors")
|
||||
R.sensor_mode()
|
||||
. = TRUE
|
||||
if("quick_action_sparks")
|
||||
R.spark_plug()
|
||||
. = TRUE
|
||||
92
tgui/packages/tgui/interfaces/Robotact/Diagnostics.tsx
Normal file
92
tgui/packages/tgui/interfaces/Robotact/Diagnostics.tsx
Normal file
@@ -0,0 +1,92 @@
|
||||
import { toTitleCase } from 'common/string';
|
||||
import { useBackend } from 'tgui/backend';
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
FitText,
|
||||
LabeledList,
|
||||
NoticeBox,
|
||||
ProgressBar,
|
||||
Section,
|
||||
Stack,
|
||||
} from 'tgui-core/components';
|
||||
|
||||
import { Data } from './types';
|
||||
|
||||
export const ComponentView = (props) => {
|
||||
const { act, data } = useBackend<Data>();
|
||||
|
||||
const { diag_functional, components } = data;
|
||||
|
||||
if (components.length) {
|
||||
components.sort((a, b) => a.name.localeCompare(b.name));
|
||||
|
||||
return (
|
||||
<Stack wrap align="flex-start" justify="space-between">
|
||||
{components.map((mod) => (
|
||||
<Stack.Item key={mod.key} basis="24%" grow ml={1}>
|
||||
<Section
|
||||
title={
|
||||
<FitText maxWidth={140} maxFontSize={18}>
|
||||
{toTitleCase(mod.name)}
|
||||
</FitText>
|
||||
}
|
||||
height={12}
|
||||
mt={1}
|
||||
buttons={
|
||||
<Button
|
||||
icon="power-off"
|
||||
disabled={mod.name === 'power cell'}
|
||||
selected={mod.toggled}
|
||||
onClick={() =>
|
||||
act('toggle_component', { component: mod.key })
|
||||
}
|
||||
/>
|
||||
}
|
||||
>
|
||||
{!!diag_functional && (
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Health">
|
||||
<ProgressBar
|
||||
mb={1}
|
||||
value={
|
||||
mod.max_damage -
|
||||
(mod.brute_damage + mod.electronics_damage)
|
||||
}
|
||||
maxValue={mod.max_damage}
|
||||
>
|
||||
{mod.max_damage -
|
||||
(mod.brute_damage + mod.electronics_damage)}{' '}
|
||||
/ {mod.max_damage}
|
||||
</ProgressBar>
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
)}
|
||||
{diag_functional ? (
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Brute Damage">
|
||||
{mod.brute_damage}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Elect Damage">
|
||||
{mod.electronics_damage}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Powered">
|
||||
{mod.is_powered || !mod.idle_usage ? (
|
||||
<Box color="good">Yes</Box>
|
||||
) : (
|
||||
<Box color="bad">No</Box>
|
||||
)}
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
) : (
|
||||
<NoticeBox danger>DIAGNOSIS UNAVAILABLE</NoticeBox>
|
||||
)}
|
||||
</Section>
|
||||
</Stack.Item>
|
||||
))}
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
return <NoticeBox danger>Diagnosis Module Offline</NoticeBox>;
|
||||
};
|
||||
71
tgui/packages/tgui/interfaces/Robotact/Modules.tsx
Normal file
71
tgui/packages/tgui/interfaces/Robotact/Modules.tsx
Normal file
@@ -0,0 +1,71 @@
|
||||
import { useBackend } from 'tgui/backend';
|
||||
import {
|
||||
Box,
|
||||
ImageButton,
|
||||
NoticeBox,
|
||||
Section,
|
||||
Stack,
|
||||
} from 'tgui-core/components';
|
||||
|
||||
import { Data, Module as ModuleData } from './types';
|
||||
|
||||
export const Modules = (props) => {
|
||||
const { act, data } = useBackend<Data>();
|
||||
|
||||
return (
|
||||
<Stack fill vertical>
|
||||
<Stack.Item grow>
|
||||
<Section
|
||||
title="Modules"
|
||||
fill
|
||||
scrollable
|
||||
height="93%"
|
||||
buttons={
|
||||
data.weapon_lock ? (
|
||||
<NoticeBox danger>Modules Locked</NoticeBox>
|
||||
) : null
|
||||
}
|
||||
>
|
||||
<Stack wrap align="space-between" justify="space-between">
|
||||
{data.modules_static.map((mod) => (
|
||||
<Stack.Item key={mod.ref} basis="32%" grow mt={1} ml={1}>
|
||||
<Module mod={mod} activated={data.modules[mod.ref]} />
|
||||
</Stack.Item>
|
||||
))}
|
||||
{data.emag_modules_static.map((mod) => (
|
||||
<Stack.Item key={mod.ref} basis="32%" grow mt={1} ml={1}>
|
||||
<Module mod={mod} activated={data.emag_modules[mod.ref]} />
|
||||
</Stack.Item>
|
||||
))}
|
||||
</Stack>
|
||||
</Section>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
const Module = (props: { mod: ModuleData; activated: number }) => {
|
||||
const { act } = useBackend();
|
||||
const { mod, activated } = props;
|
||||
return (
|
||||
<ImageButton
|
||||
dmIcon={mod.icon}
|
||||
dmIconState={mod.icon_state}
|
||||
selected={activated}
|
||||
imageSize={128}
|
||||
fluid
|
||||
onClick={() => act('toggle_module', { ref: mod.ref })}
|
||||
onRightClick={() => act('activate_module', { ref: mod.ref })}
|
||||
tooltip={activated ? 'Right click to trigger' : ''}
|
||||
tooltipPosition="bottom-end"
|
||||
position="relative"
|
||||
>
|
||||
{!!activated && (
|
||||
<Box position="absolute" top={0.5} right={0.5} fontSize={1.5}>
|
||||
{activated}
|
||||
</Box>
|
||||
)}
|
||||
<Box>{mod.name}</Box>
|
||||
</ImageButton>
|
||||
);
|
||||
};
|
||||
205
tgui/packages/tgui/interfaces/Robotact/StatusScreen.tsx
Normal file
205
tgui/packages/tgui/interfaces/Robotact/StatusScreen.tsx
Normal file
@@ -0,0 +1,205 @@
|
||||
import { useBackend } from 'tgui/backend';
|
||||
import {
|
||||
Box,
|
||||
ImageButton,
|
||||
LabeledList,
|
||||
NoticeBox,
|
||||
ProgressBar,
|
||||
Section,
|
||||
Stack,
|
||||
} from 'tgui-core/components';
|
||||
|
||||
import { Data } from './types';
|
||||
|
||||
const quick_actions: {
|
||||
name: string;
|
||||
icon: string;
|
||||
icon_state: string;
|
||||
eventName: string;
|
||||
}[] = [
|
||||
{
|
||||
name: 'Communicator',
|
||||
icon: 'icons/obj/device.dmi',
|
||||
icon_state: 'communicator',
|
||||
eventName: 'quick_action_comm',
|
||||
},
|
||||
{
|
||||
name: 'PDA',
|
||||
icon: 'icons/obj/pda_vr.dmi',
|
||||
icon_state: 'pda',
|
||||
eventName: 'quick_action_pda',
|
||||
},
|
||||
{
|
||||
name: 'Crew Manifest',
|
||||
icon: 'icons/obj/pda_vr.dmi',
|
||||
icon_state: 'cart',
|
||||
eventName: 'quick_action_crew_manifest',
|
||||
},
|
||||
{
|
||||
name: 'Law Manager',
|
||||
icon: 'icons/mob/screen1_robot.dmi',
|
||||
icon_state: 'harm',
|
||||
eventName: 'quick_action_law_manager',
|
||||
},
|
||||
{
|
||||
name: 'Alarm Monitor',
|
||||
icon: 'icons/obj/modular_console.dmi',
|
||||
icon_state: 'alert-green',
|
||||
eventName: 'quick_action_alarm_monitoring',
|
||||
},
|
||||
{
|
||||
name: 'Power Monitor',
|
||||
icon: 'icons/obj/modular_console.dmi',
|
||||
icon_state: 'power_monitor',
|
||||
eventName: 'quick_action_power_monitoring',
|
||||
},
|
||||
{
|
||||
name: 'Take Image',
|
||||
icon: 'icons/obj/items.dmi',
|
||||
icon_state: 'camera',
|
||||
eventName: 'quick_action_take_image',
|
||||
},
|
||||
{
|
||||
name: 'View Images',
|
||||
icon: 'icons/obj/items.dmi',
|
||||
icon_state: 'film',
|
||||
eventName: 'quick_action_view_images',
|
||||
},
|
||||
{
|
||||
name: 'Delete Images',
|
||||
icon: 'icons/obj/items.dmi',
|
||||
icon_state: 'photo',
|
||||
eventName: 'quick_action_delete_images',
|
||||
},
|
||||
{
|
||||
name: 'Toggle Lights',
|
||||
icon: 'icons/obj/lighting.dmi',
|
||||
icon_state: 'flashlight',
|
||||
eventName: 'quick_action_flashlight',
|
||||
},
|
||||
{
|
||||
name: 'Toggle Sensor Augmentation',
|
||||
icon: 'icons/inventory/eyes/item.dmi',
|
||||
icon_state: 'sec_hud',
|
||||
eventName: 'quick_action_sensors',
|
||||
},
|
||||
{
|
||||
name: 'Emit Sparks',
|
||||
icon: 'icons/effects/effects.dmi',
|
||||
icon_state: 'sparks',
|
||||
eventName: 'quick_action_sparks',
|
||||
},
|
||||
];
|
||||
|
||||
export const StatusScreen = (props) => {
|
||||
const { act } = useBackend<Data>();
|
||||
|
||||
return (
|
||||
<Stack vertical fill height="94%">
|
||||
<Stack.Item basis="20%">
|
||||
<Stack fill>
|
||||
<Stack.Item grow>
|
||||
<Configuration />
|
||||
</Stack.Item>
|
||||
<Stack.Item grow>
|
||||
<Status />
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Stack.Item>
|
||||
<Stack.Item grow>
|
||||
<Section title="Quick Actions" fill scrollable>
|
||||
<Stack>
|
||||
<Stack.Item grow>
|
||||
{quick_actions
|
||||
.slice(0, quick_actions.length / 2)
|
||||
.map((action) => (
|
||||
<ImageButton
|
||||
key={action.name}
|
||||
dmIcon={action.icon}
|
||||
dmIconState={action.icon_state}
|
||||
imageSize={48}
|
||||
onClick={() => act(action.eventName)}
|
||||
fluid
|
||||
>
|
||||
{action.name}
|
||||
</ImageButton>
|
||||
))}
|
||||
</Stack.Item>
|
||||
<Stack.Item grow>
|
||||
{quick_actions.slice(quick_actions.length / 2).map((action) => (
|
||||
<ImageButton
|
||||
key={action.name}
|
||||
dmIcon={action.icon}
|
||||
dmIconState={action.icon_state}
|
||||
imageSize={48}
|
||||
onClick={() => act(action.eventName)}
|
||||
fluid
|
||||
>
|
||||
{action.name}
|
||||
</ImageButton>
|
||||
))}
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Section>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
const Configuration = (props) => {
|
||||
const { data } = useBackend<Data>();
|
||||
|
||||
const { name, module_name, ai } = data;
|
||||
return (
|
||||
<Section title="Configuration" fill>
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Unit">{name}</LabeledList.Item>
|
||||
<LabeledList.Item label="Type">{module_name}</LabeledList.Item>
|
||||
<LabeledList.Item label="AI">
|
||||
{ai ? <Box color="good">{ai}</Box> : <Box color="average">None</Box>}
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
const Status = (props) => {
|
||||
const { data } = useBackend<Data>();
|
||||
|
||||
const { charge, max_charge, health, max_health } = data;
|
||||
|
||||
return (
|
||||
<Section title="Status" fill>
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Charge">
|
||||
{charge && max_charge ? (
|
||||
<ProgressBar
|
||||
value={charge}
|
||||
maxValue={max_charge}
|
||||
ranges={{
|
||||
good: [max_charge * 0.75, Number.POSITIVE_INFINITY],
|
||||
average: [max_charge * 0.3, max_charge * 0.75],
|
||||
bad: [Number.NEGATIVE_INFINITY, max_charge * 0.3],
|
||||
}}
|
||||
>
|
||||
{charge} / {max_charge}
|
||||
</ProgressBar>
|
||||
) : (
|
||||
<NoticeBox danger>NO CELL INSTALLED</NoticeBox>
|
||||
)}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Chassis Integrity">
|
||||
<ProgressBar
|
||||
value={health}
|
||||
maxValue={max_health}
|
||||
ranges={{
|
||||
good: [max_health * 0.75, Number.POSITIVE_INFINITY],
|
||||
average: [max_health * 0.3, max_health * 0.75],
|
||||
bad: [Number.NEGATIVE_INFINITY, max_health * 0.3],
|
||||
}}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
90
tgui/packages/tgui/interfaces/Robotact/index.tsx
Normal file
90
tgui/packages/tgui/interfaces/Robotact/index.tsx
Normal file
@@ -0,0 +1,90 @@
|
||||
import { useState } from 'react';
|
||||
import { useBackend } from 'tgui/backend';
|
||||
import { Window } from 'tgui/layouts';
|
||||
import { Button, NoticeBox, Stack, Tabs } from 'tgui-core/components';
|
||||
|
||||
import { ComponentView } from './Diagnostics';
|
||||
import { Modules } from './Modules';
|
||||
import { StatusScreen } from './StatusScreen';
|
||||
import { Data } from './types';
|
||||
|
||||
export const Robotact = (props) => {
|
||||
const { act, data } = useBackend<Data>();
|
||||
|
||||
let content = <NoModuleWarning />;
|
||||
|
||||
if (data.module_name) {
|
||||
content = <MainScreen />;
|
||||
}
|
||||
|
||||
return (
|
||||
<Window width={800} height={600} theme="ntos">
|
||||
<Window.Content>{content}</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
|
||||
const NoModuleWarning = (props) => {
|
||||
const { act } = useBackend();
|
||||
|
||||
return (
|
||||
<Stack fill align="center" justify="center" vertical>
|
||||
<Stack.Item>
|
||||
<NoticeBox danger fontSize={2} style={{ borderRadius: '6px' }} p={4}>
|
||||
No Module Activated
|
||||
</NoticeBox>
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Button icon="eyedropper" onClick={() => act('select_module')}>
|
||||
Select A Module
|
||||
</Button>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
const MainScreen = (props) => {
|
||||
const [screen, setScreen] = useState(0);
|
||||
|
||||
let content;
|
||||
switch (screen) {
|
||||
case 0:
|
||||
content = <StatusScreen />;
|
||||
break;
|
||||
case 1:
|
||||
content = <ComponentView />;
|
||||
break;
|
||||
case 2:
|
||||
content = <Modules />;
|
||||
break;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Tabs>
|
||||
<Tabs.Tab
|
||||
selected={screen === 0}
|
||||
onClick={() => setScreen(0)}
|
||||
icon="battery-full"
|
||||
>
|
||||
Status
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab
|
||||
selected={screen === 1}
|
||||
onClick={() => setScreen(1)}
|
||||
icon="notes-medical"
|
||||
>
|
||||
Diagnostics
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab
|
||||
selected={screen === 2}
|
||||
onClick={() => setScreen(2)}
|
||||
icon="wrench"
|
||||
>
|
||||
Modules
|
||||
</Tabs.Tab>
|
||||
</Tabs>
|
||||
{content}
|
||||
</>
|
||||
);
|
||||
};
|
||||
43
tgui/packages/tgui/interfaces/Robotact/types.ts
Normal file
43
tgui/packages/tgui/interfaces/Robotact/types.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { BooleanLike } from 'common/react';
|
||||
|
||||
export type Component = {
|
||||
key: string;
|
||||
name: string;
|
||||
brute_damage: number;
|
||||
electronics_damage: number;
|
||||
max_damage: number;
|
||||
idle_usage: number;
|
||||
is_powered: boolean;
|
||||
toggled: boolean;
|
||||
};
|
||||
|
||||
export type Module = {
|
||||
ref: string;
|
||||
name: string;
|
||||
activated: number;
|
||||
icon: string;
|
||||
icon_state: string;
|
||||
};
|
||||
|
||||
export type Data = {
|
||||
name: string;
|
||||
module_name: string | null;
|
||||
ai: string;
|
||||
charge: number | null;
|
||||
max_charge: number | null;
|
||||
weapon_lock: BooleanLike;
|
||||
|
||||
health: number;
|
||||
max_health: number;
|
||||
|
||||
// Modules
|
||||
modules_static: Module[];
|
||||
emag_modules_static: Module[];
|
||||
|
||||
modules: Record<string, number>;
|
||||
emag_modules: Record<string, number>;
|
||||
|
||||
// Diagnosis
|
||||
diag_functional: BooleanLike;
|
||||
components: Component[];
|
||||
};
|
||||
@@ -3311,6 +3311,7 @@
|
||||
#include "code\modules\mob\living\silicon\robot\robot_items.dm"
|
||||
#include "code\modules\mob\living\silicon\robot\robot_movement.dm"
|
||||
#include "code\modules\mob\living\silicon\robot\robot_remote_control.dm"
|
||||
#include "code\modules\mob\living\silicon\robot\robot_ui.dm"
|
||||
#include "code\modules\mob\living\silicon\robot\dogborg\dog_modules_vr.dm"
|
||||
#include "code\modules\mob\living\silicon\robot\dogborg\dog_modules_yw.dm"
|
||||
#include "code\modules\mob\living\silicon\robot\dogborg\dog_sleeper_vr.dm"
|
||||
|
||||
Reference in New Issue
Block a user