diff --git a/baystation12.dme b/baystation12.dme
index 93cd06177e0..e3a4437f1a6 100644
--- a/baystation12.dme
+++ b/baystation12.dme
@@ -1388,6 +1388,7 @@
#include "code\modules\modular_computers\file_system\computer_file.dm"
#include "code\modules\modular_computers\file_system\data.dm"
#include "code\modules\modular_computers\file_system\program.dm"
+#include "code\modules\modular_computers\file_system\programs\configurator.dm"
#include "code\modules\modular_computers\file_system\programs\engineering.dm"
#include "code\modules\modular_computers\hardware\card_slot.dm"
#include "code\modules\modular_computers\hardware\hard_drive.dm"
diff --git a/code/modules/modular_computers/computers/item/modular_computer.dm b/code/modules/modular_computers/computers/item/modular_computer.dm
index a57c2e4e7ca..b4429a00d8d 100644
--- a/code/modules/modular_computers/computers/item/modular_computer.dm
+++ b/code/modules/modular_computers/computers/item/modular_computer.dm
@@ -10,7 +10,7 @@
var/open = 1 // Whether the computer is active/opened/it's screen is on.
var/datum/computer_file/program/active_program = null // A currently active program running on the computer.
var/hardware_flag = 0 // A flag that describes this device type
-
+ var/last_power_usage = 0
// Modular computers can run on various devices. Each DEVICE (Laptop, Console, Tablet,..)
// must have it's own DMI file. Icon states must be called exactly the same in all files, but may look differently
// If you create a program which is limited to Laptops and Consoles you don't have to add it's icon_state overlay for Tablets too, for example.
@@ -148,6 +148,7 @@
// Process currently calls handle_power(), may be expanded in future if more things are added.
/obj/item/modular_computer/process()
if(!enabled) // The computer is turned off
+ last_power_usage = 0
return 0
if(active_program && active_program.requires_ntnet && !get_ntnet_status(active_program.requires_ntnet_feature)) // Active program requires NTNet to run but we've just lost connection. Crash.
@@ -188,6 +189,8 @@
data["PC_ntneticon"] = "sig_low.gif"
if(2)
data["PC_ntneticon"] = "sig_high.gif"
+ if(3)
+ data["PC_ntneticon"] = "sig_lan.gif"
data["PC_stationtime"] = worldtime2text()
data["PC_hasheader"] = 1
@@ -197,6 +200,9 @@
// Installs programs necessary for computer function.
// TODO: Implement program for downloading of other programs, and replace hardcoded program addition here
/obj/item/modular_computer/proc/install_default_programs()
+ hard_drive.store_file(new/datum/computer_file/program/computerconfig(src)) // Computer configuration utility, allows hardware control and displays more info than status bar
+
+ //TODO: Remove once downloading is implemented
hard_drive.store_file(new/datum/computer_file/program/alarm_monitor(src))
hard_drive.store_file(new/datum/computer_file/program/power_monitor(src))
hard_drive.store_file(new/datum/computer_file/program/atmos_control(src))
@@ -227,6 +233,16 @@
if( href_list["PC_exit"] )
kill_program()
return
+ if( href_list["PC_enable_component"] )
+ var/datum/computer_hardware/H = find_hardware_by_name(href_list["PC_enable_component"])
+ if(H && istype(H) && !H.enabled)
+ H.enabled = 1
+ return
+ if( href_list["PC_disable_component"] )
+ var/datum/computer_hardware/H = find_hardware_by_name(href_list["PC_disable_component"])
+ if(H && istype(H) && H.enabled)
+ H.enabled = 0
+ return
if( href_list["PC_shutdown"] )
kill_program(1)
visible_message("\The [src] shuts down.")
@@ -278,6 +294,7 @@
if(battery)
battery.use(power_usage * CELLRATE)
+ last_power_usage = power_usage
/obj/item/modular_computer/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
if(istype(W, /obj/item/weapon/card/id)) // ID Card, try to insert it.
@@ -295,4 +312,16 @@
user << "You insert \the [I] into \the [src]."
return
- ..()
\ No newline at end of file
+ ..()
+
+// Checks all hardware pieces to determine if name matches, if yes, returns the hardware piece, otherwise returns null
+/obj/item/modular_computer/proc/find_hardware_by_name(var/name)
+ if(hard_drive && (hard_drive.name == name))
+ return hard_drive
+ if(network_card && (network_card.name == name))
+ return network_card
+ if(nano_printer && (nano_printer.name == name))
+ return nano_printer
+ if(card_slot && (card_slot.name == name))
+ return card_slot
+ return null
\ No newline at end of file
diff --git a/code/modules/modular_computers/computers/machinery/modular_computer.dm b/code/modules/modular_computers/computers/machinery/modular_computer.dm
index 4a12383eb29..0c3435e42e7 100644
--- a/code/modules/modular_computers/computers/machinery/modular_computer.dm
+++ b/code/modules/modular_computers/computers/machinery/modular_computer.dm
@@ -10,6 +10,7 @@
var/battery_powered = 0 // Whether computer should be battery powered. It is set automatically
use_power = 0
var/hardware_flag = 0 // A flag that describes this device type
+ var/last_power_usage = 0 // Power usage during last tick
// Modular computers can run on various devices. Each DEVICE (Laptop, Console, Tablet,..)
// must have it's own DMI file. Icon states must be called exactly the same in all files, but may look differently
@@ -76,9 +77,16 @@
card_slot.stored_card = null
user << "You remove the card from \the [src]"
+/obj/machinery/modular_computer/New()
+ ..()
+ install_default_programs()
+
// Installs programs necessary for computer function.
// TODO: Implement program for downloading of other programs, and replace hardcoded program addition here
/obj/machinery/modular_computer/proc/install_default_programs()
+ hard_drive.store_file(new/datum/computer_file/program/computerconfig(src)) // Computer configuration utility, allows hardware control and displays more info than status bar
+
+ //TODO: Remove once downloading is implemented
hard_drive.store_file(new/datum/computer_file/program/alarm_monitor(src))
hard_drive.store_file(new/datum/computer_file/program/power_monitor(src))
hard_drive.store_file(new/datum/computer_file/program/atmos_control(src))
@@ -143,6 +151,7 @@
/obj/machinery/modular_computer/process()
if(!enabled) // The computer is turned off
use_power = 0
+ last_power_usage = 0
return 0
if(active_program && active_program.requires_ntnet && !get_ntnet_status(active_program.requires_ntnet_feature)) // Active program requires NTNet to run but we've just lost connection. Crash.
@@ -185,6 +194,8 @@
data["PC_ntneticon"] = "sig_low.gif"
if(2)
data["PC_ntneticon"] = "sig_high.gif"
+ if(3)
+ data["PC_ntneticon"] = "sig_lan.gif"
if(tesla_link && tesla_link.enabled && powered())
data["PC_apclinkicon"] = "charging.gif"
@@ -212,6 +223,20 @@
else
return 0
+// Checks all hardware pieces to determine if name matches, if yes, returns the hardware piece, otherwise returns null
+/obj/machinery/modular_computer/proc/find_hardware_by_name(var/name)
+ if(hard_drive && (hard_drive.name == name))
+ return hard_drive
+ if(network_card && (network_card.name == name))
+ return network_card
+ if(tesla_link && (tesla_link.name == name))
+ return tesla_link
+ if(nano_printer && (nano_printer.name == name))
+ return nano_printer
+ if(card_slot && (card_slot.name == name))
+ return card_slot
+ return null
+
// Handles user's GUI input
/obj/machinery/modular_computer/Topic(href, href_list)
if(..())
@@ -219,6 +244,16 @@
if( href_list["PC_exit"] )
kill_program()
return
+ if( href_list["PC_enable_component"] )
+ var/datum/computer_hardware/H = find_hardware_by_name(href_list["PC_enable_component"])
+ if(H && istype(H) && !H.enabled)
+ H.enabled = 1
+ return
+ if( href_list["PC_disable_component"] )
+ var/datum/computer_hardware/H = find_hardware_by_name(href_list["PC_disable_component"])
+ if(H && istype(H) && H.enabled)
+ H.enabled = 0
+ return
if( href_list["PC_shutdown"] )
kill_program(1)
visible_message("\The [src] shuts down.")
@@ -291,6 +326,7 @@
use_power = 0
if (battery)
battery.use(power_usage * CELLRATE)
+ last_power_usage = power_usage
// Modular computers can have battery in them, we handle power in previous proc, so prevent this from messing it up for us.
/obj/machinery/modular_computer/power_change()
diff --git a/code/modules/modular_computers/computers/machinery/modular_console.dm b/code/modules/modular_computers/computers/machinery/modular_console.dm
index 71f21ce51e9..2f24b3b0b51 100644
--- a/code/modules/modular_computers/computers/machinery/modular_console.dm
+++ b/code/modules/modular_computers/computers/machinery/modular_console.dm
@@ -8,14 +8,16 @@
icon_state_unpowered = "console"
screen_icon_state_menu = "menu"
keyboard_icon_state_menu = "kb_menu"
+ hardware_flag = PROGRAM_CONSOLE
anchored = 1
density = 1
/obj/machinery/modular_computer/console/New()
- ..()
battery = null
network_card = new/datum/computer_hardware/network_card/wired(src)
tesla_link = new/datum/computer_hardware/tesla_link(src)
tesla_link.enabled = 1
+ tesla_link.critical = 1 // Consoles don't usually come with cells, and this prevents people from disabling their only power source, as they wouldn't be able to enable it again.
hard_drive = new/datum/computer_hardware/hard_drive/super(src) // Consoles generally have better HDDs due to lower space limitations
- install_default_programs() // Consoles come with set of department-specific programs when constructed.
\ No newline at end of file
+ ..()
+ update_icon()
\ No newline at end of file
diff --git a/code/modules/modular_computers/computers/machinery/modular_laptop.dm b/code/modules/modular_computers/computers/machinery/modular_laptop.dm
index e193b976b60..bfe9dcb43d8 100644
--- a/code/modules/modular_computers/computers/machinery/modular_laptop.dm
+++ b/code/modules/modular_computers/computers/machinery/modular_laptop.dm
@@ -52,7 +52,7 @@
name = "laptop computer"
desc = "A portable computer"
var/obj/item/laptop/portable = null // Portable version of this computer, dropped on alt-click to allow transport. Used by laptops.
- battery_powered = 1 // Laptops have integrated battery
+ hardware_flag = PROGRAM_LAPTOP
icon_state_unpowered = "laptop-open" // Icon state when the computer is turned off
icon = 'icons/obj/modular_laptop.dmi'
icon_state = "laptop-open"
diff --git a/code/modules/modular_computers/file_system/program.dm b/code/modules/modular_computers/file_system/program.dm
index 653d6dfdce6..f837301c68c 100644
--- a/code/modules/modular_computers/file_system/program.dm
+++ b/code/modules/modular_computers/file_system/program.dm
@@ -101,8 +101,8 @@
if(ui)
ui.close()
return 0
- if(NM)
- NM.ui_interact(user, ui_key, ui, force_open)
+ if(istype(NM))
+ NM.ui_interact(user, ui_key, null, force_open)
return 0
return 1
diff --git a/code/modules/modular_computers/file_system/programs/configurator.dm b/code/modules/modular_computers/file_system/programs/configurator.dm
new file mode 100644
index 00000000000..7d2698023ca
--- /dev/null
+++ b/code/modules/modular_computers/file_system/programs/configurator.dm
@@ -0,0 +1,82 @@
+// This is special hardware configuration program.
+// It is to be used only with modular computers.
+// It allows you to toggle components of your device.
+
+/datum/computer_file/program/computerconfig
+ filename = "compconfig"
+ filedesc = "Computer Configuration Tool"
+ program_icon_state = "generic"
+ unsendable = 1
+ undeletable = 1
+ size = 2
+ nanomodule_path = /datum/nano_module/computer_configurator/
+
+/datum/nano_module/computer_configurator
+ name = "NTOS Computer Configuration Tool"
+ var/obj/machinery/modular_computer/stationary = null
+ var/obj/item/modular_computer/movable = null
+
+/datum/nano_module/computer_configurator/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state)
+ if(program)
+ stationary = program.computer
+ movable = program.computer
+
+ if(!istype(stationary))
+ stationary = null
+ if(!istype(movable))
+ movable = null
+
+ // No computer connection, we can't get data from that.
+ if(!movable && !stationary)
+ return 0
+
+ var/list/data = list()
+
+ if(program)
+ data = program.get_header_data()
+
+ var/list/hardware = list()
+ if(stationary)
+ hardware.Add(stationary.network_card)
+ hardware.Add(stationary.hard_drive)
+ hardware.Add(stationary.tesla_link)
+ hardware.Add(stationary.card_slot)
+ hardware.Add(stationary.nano_printer)
+ data["disk_size"] = stationary.hard_drive.max_capacity
+ data["disk_used"] = stationary.hard_drive.used_capacity
+ data["power_usage"] = stationary.last_power_usage
+ data["battery_exists"] = stationary.battery ? 1 : 0
+ if(stationary.battery)
+ data["battery_rating"] = stationary.battery.maxcharge
+ data["battery_percent"] = round(stationary.battery.percent())
+ else if(movable)
+ hardware.Add(movable.network_card)
+ hardware.Add(movable.hard_drive)
+ hardware.Add(movable.card_slot)
+ hardware.Add(movable.nano_printer)
+ data["disk_size"] = movable.hard_drive.max_capacity
+ data["disk_used"] = movable.hard_drive.used_capacity
+ data["power_usage"] = movable.last_power_usage
+ data["battery_exists"] = movable.battery ? 1 : 0
+ if(movable.battery)
+ data["battery_rating"] = movable.battery.maxcharge
+ data["battery_percent"] = round(movable.battery.percent())
+
+ var/list/all_entries[0]
+ for(var/datum/computer_hardware/H in hardware)
+ all_entries.Add(list(list(
+ "name" = H.name,
+ "desc" = H.desc,
+ "enabled" = H.enabled,
+ "critical" = H.critical,
+ "powerusage" = H.power_usage
+ )))
+
+ data["hardware"] = all_entries
+ ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
+ if (!ui)
+ ui = new(user, src, ui_key, "laptop_configuration.tmpl", "NTOS Configuration Utility", 575, 700, state = state)
+ ui.auto_update_layout = 1
+ ui.set_initial_data(data)
+ ui.open()
+ ui.set_auto_update(1)
\ No newline at end of file
diff --git a/code/modules/modular_computers/file_system/programs/engineering.dm b/code/modules/modular_computers/file_system/programs/engineering.dm
index 562bd0a2251..234d6518ddb 100644
--- a/code/modules/modular_computers/file_system/programs/engineering.dm
+++ b/code/modules/modular_computers/file_system/programs/engineering.dm
@@ -27,7 +27,7 @@
required_access = access_atmospherics
requires_ntnet = 1
requires_ntnet_feature = NTNET_SYSTEMCONTROL
- usage_flags = PROGRAM_LAPTOP & PROGRAM_CONSOLE
+ usage_flags = PROGRAM_LAPTOP | PROGRAM_CONSOLE
size = 17
/datum/computer_file/program/rcon_console
@@ -39,7 +39,7 @@
required_access = access_engine
requires_ntnet = 1
requires_ntnet_feature = NTNET_SYSTEMCONTROL
- usage_flags = PROGRAM_LAPTOP & PROGRAM_CONSOLE
+ usage_flags = PROGRAM_LAPTOP | PROGRAM_CONSOLE
size = 25
/datum/computer_file/program/suit_sensors
diff --git a/code/modules/nano/nanoui.dm b/code/modules/nano/nanoui.dm
index 4c61718fffc..ea201f43494 100644
--- a/code/modules/nano/nanoui.dm
+++ b/code/modules/nano/nanoui.dm
@@ -392,6 +392,11 @@ nanoui is used to open and update nano browser uis
if(!user.client)
return
+ // An attempted fix to UIs sometimes locking up spamming runtime errors due to src_object being null for whatever reason.
+ // This hard-deletes the UI, preventing the device that uses the UI from being locked up permanently.
+ if(!src_object)
+ del(src)
+
var/window_size = ""
if (width && height)
window_size = "size=[width]x[height];"
diff --git a/nano/images/status_icons/sig_lan.gif b/nano/images/status_icons/sig_lan.gif
new file mode 100644
index 00000000000..07ba929f7f3
Binary files /dev/null and b/nano/images/status_icons/sig_lan.gif differ
diff --git a/nano/templates/laptop_configuration.tmpl b/nano/templates/laptop_configuration.tmpl
new file mode 100644
index 00000000000..69af3bd6c0f
--- /dev/null
+++ b/nano/templates/laptop_configuration.tmpl
@@ -0,0 +1,70 @@
+Welcome to computer configuration utility. Please consult your system administrator if you have any questions about your device.
+Power Supply
+
+ Battery Status:
+
+{{if data.battery_exists}}
+
+ Active
+
+
+ Battery Rating:
+
+
+ {{:data.battery_rating}}
+
+
+ Battery Charge:
+
+
+ {{:helper.displayBar(data.battery_percent, 0, 100, (data.battery_percent <= 25) ? 'bad' : (data.battery_percent <= 50) ? 'average' : 'good')}}
+ {{:data.battery_percent}} %
+
+{{else}}
+
+ Not Available
+
+{{/if}}
+
+ Power Usage:
+
+
+ {{:data.power_usage}}W
+
+File System
+
+ Used Capacity:
+
+
+ {{:helper.displayBar(data.disk_used, 0, data.disk_size, 'good')}}
+ {{:data.disk_used}}GQ / {{:data.disk_size}}GQ
+
+Computer Components
+{{for data.hardware}}
+ {{:value.name}}
+ {{:value.desc}}
+
+ State:
+
+
+ {{:value.enabled ? "Enabled" : "Disabled"}}
+
+
+ Power Usage:
+
+
+ {{:value.powerusage}}W
+
+ {{if !value.critical}}
+
+ Toggle Component:
+
+
+ {{:helper.link("ON", null, {'PC_enable_component' : value.name}, value.enabled ? 'disabled' : null)}}
+ {{:helper.link("OFF", null, {'PC_disable_component' : value.name}, value.enabled ? null : 'disabled')}}
+
+ {{/if}}
+
+{{/for}}
+
+NTOS v2.0.4b Copyright NanoTrasen 2557 - 2559
\ No newline at end of file
diff --git a/nano/templates/laptop_mainscreen.tmpl b/nano/templates/laptop_mainscreen.tmpl
index bc05416e830..649d1d3b93a 100644
--- a/nano/templates/laptop_mainscreen.tmpl
+++ b/nano/templates/laptop_mainscreen.tmpl
@@ -1,6 +1,6 @@
No program loaded. Please select program from list below.
{{for data.programs}}
- | {{:helper.link(value.desc, 'icon-power', {'PC_runprogram' : value.name})}}
+ |
| {{:helper.link(value.desc, null, {'PC_runprogram' : value.name})}}
{{/for}}
|
\ No newline at end of file
diff --git a/nano/templates/layout_default.tmpl b/nano/templates/layout_default.tmpl
index c7f2bbc01a4..a5fd6f5804b 100644
--- a/nano/templates/layout_default.tmpl
+++ b/nano/templates/layout_default.tmpl
@@ -22,9 +22,9 @@
- | {{:helper.link('Shutdown', 'icon-power', {'PC_shutdown' : 1})}}
+ | {{:helper.link('Shutdown', null, {'PC_shutdown' : 1})}}
{{if data.PC_showexitprogram}}
- | {{:helper.link('Exit Program', 'icon-close', {'PC_exit' : 1})}}
+ | {{:helper.link('Exit Program', null, {'PC_exit' : 1})}}
{{/if}}
|