diff --git a/code/__defines/misc.dm b/code/__defines/misc.dm
index 1a74eeccbc..b570aee7c6 100644
--- a/code/__defines/misc.dm
+++ b/code/__defines/misc.dm
@@ -188,9 +188,9 @@
#define NTNET_SYSTEMCONTROL 4 // Control of various systems, RCon, air alarm control, etc.
// NTNet transfer speeds, used when downloading/uploading a file/program.
-#define NTNETSPEED_LOWSIGNAL 0.025 // GQ/s transfer speed when the device is wirelessly connected and on Low signal
-#define NTNETSPEED_HIGHSIGNAL 0.1 // GQ/s transfer speed when the device is wirelessly connected and on High signal
-#define NTNETSPEED_ETHERNET 0.5 // GQ/s transfer speed when the device is using wired connection
+#define NTNETSPEED_LOWSIGNAL 0.1 // GQ/s transfer speed when the device is wirelessly connected and on Low signal
+#define NTNETSPEED_HIGHSIGNAL 0.5 // GQ/s transfer speed when the device is wirelessly connected and on High signal
+#define NTNETSPEED_ETHERNET 1.0 // GQ/s transfer speed when the device is using wired connection
// Program bitflags
#define PROGRAM_ALL 7
diff --git a/code/modules/modular_computers/computers/item/modular_computer.dm b/code/modules/modular_computers/computers/item/modular_computer.dm
index bc041adbd5..534f6b573e 100644
--- a/code/modules/modular_computers/computers/item/modular_computer.dm
+++ b/code/modules/modular_computers/computers/item/modular_computer.dm
@@ -28,7 +28,12 @@
var/icon_state_menu = "menu" // Icon state overlay when the computer is turned on, but no program is loaded that would override the screen.
var/max_hardware_size = 0 // Maximal hardware size. Currently, tablets have 1, laptops 2 and consoles 3. Limits what hardware types can be installed.
var/steel_sheet_cost = 5 // Amount of steel sheets refunded when disassembling an empty frame of this computer.
+ var/light_strength = 0
+ // Damage of the chassis. If the chassis takes too much damage it will break apart.
+ var/damage = 0 // Current damage level
+ var/broken_damage = 50 // Damage level at which the computer ceases to operate
+ var/max_damage = 100 // Damage level at which the computer breaks apart.
// Important hardware (must be installed for computer to work)
var/obj/item/weapon/computer_hardware/processor_unit/processor_unit // CPU. Without it the computer won't run. Better CPUs can run more programs at once.
@@ -59,6 +64,22 @@
proc_eject_id(usr)
+// Eject ID card from computer, if it has ID slot with card inside.
+/obj/item/modular_computer/verb/eject_usb()
+ set name = "Eject Portable Device"
+ set category = "Object"
+ set src in view(1)
+
+ if(usr.incapacitated() || !istype(usr, /mob/living))
+ usr << "You can't do that."
+ return
+
+ if(!Adjacent(usr))
+ usr << "You can't reach it."
+ return
+
+ proc_eject_usb(usr)
+
/obj/item/modular_computer/proc/proc_eject_id(mob/user)
if(!user)
user = usr
@@ -82,6 +103,17 @@
update_uis()
user << "You remove the card from \the [src]"
+/obj/item/modular_computer/proc/proc_eject_usb(mob/user)
+ if(!user)
+ user = usr
+
+ if(!portable_drive)
+ user << "There is no portable device connected to \the [src]."
+ return
+
+ uninstall_component(user, portable_drive)
+ update_uis()
+
/obj/item/modular_computer/attack_ghost(var/mob/observer/dead/user)
if(enabled)
ui_interact(user)
@@ -99,6 +131,13 @@
user << "You emag \the [src]. It's screen briefly shows a \"OVERRIDE ACCEPTED: New software downloads available.\" message."
return 1
+/obj/item/modular_computer/examine(var/mob/user)
+ ..()
+ if(damage > broken_damage)
+ user << "It is heavily damaged!"
+ else if(damage)
+ user << "It is damaged."
+
/obj/item/modular_computer/New()
START_PROCESSING(SSobj, src)
update_icon()
@@ -108,7 +147,7 @@
kill_program(1)
STOP_PROCESSING(SSobj, src)
for(var/obj/item/weapon/computer_hardware/CH in src.get_all_components())
- qdel(CH)
+ uninstall_component(null, CH)
return ..()
/obj/item/modular_computer/update_icon()
@@ -116,7 +155,9 @@
overlays.Cut()
if(!enabled)
+ set_light(0)
return
+ set_light(light_strength)
if(active_program)
overlays.Add(active_program.program_icon_state ? active_program.program_icon_state : icon_state_menu)
else
@@ -175,9 +216,27 @@
else
turn_on(user)
+/obj/item/modular_computer/proc/break_apart()
+ visible_message("\The [src] breaks apart!")
+ var/turf/newloc = get_turf(src)
+ new /obj/item/stack/material/steel(newloc, round(steel_sheet_cost/2))
+ for(var/obj/item/weapon/computer_hardware/H in get_all_components())
+ uninstall_component(null, H)
+ H.forceMove(newloc)
+ if(prob(25))
+ H.take_damage(rand(10,30))
+ relay_qdel()
+ qdel()
+
/obj/item/modular_computer/proc/turn_on(var/mob/user)
var/issynth = issilicon(user) // Robots and AIs get different activation messages.
- if(processor_unit && ((battery_module && battery_module.battery.charge) || check_power_override())) // Battery-run and charged or non-battery but powered by APC.
+ if(damage > broken_damage)
+ if(issynth)
+ user << "You send an activation signal to \the [src], but it responds with an error code. It must be damaged."
+ else
+ user << "You press the power button, but the computer fails to boot up, displaying variety of errors before shutting down again."
+ return
+ if(processor_unit && ((battery_module && battery_module.battery.charge && battery_module.check_functionality()) || check_power_override())) // Battery-run and charged or non-battery but powered by APC.
if(issynth)
user << "You send an activation signal to \the [src], turning it on"
else
@@ -197,6 +256,10 @@
last_power_usage = 0
return 0
+ if(damage > broken_damage)
+ shutdown_computer()
+ 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.
active_program.event_networkfailure(0)
@@ -350,12 +413,13 @@
var/mob/user = usr
if(hard_drive)
P = hard_drive.find_file_by_name(prog)
- P.computer = src
if(!P || !istype(P)) // Program not found or it's not executable program.
user << "\The [src]'s screen shows \"I/O ERROR - Unable to run program\" warning."
return
+ P.computer = src
+
if(!P.is_supported_by_hardware(hardware_flag, 1, user))
return
@@ -378,9 +442,9 @@
update_uis()
// Used in following function to reduce copypaste
-/obj/item/modular_computer/proc/power_failure()
+/obj/item/modular_computer/proc/power_failure(var/malfunction = 0)
if(enabled) // Shut down the computer
- visible_message("\The [src]'s screen flickers \"BATTERY CRITICAL\" warning as it shuts down unexpectedly.")
+ visible_message("\The [src]'s screen flickers \"BATTERY [malfunction ? "MALFUNCTION" : "CRITICAL"]\" warning as it shuts down unexpectedly.")
if(active_program)
active_program.event_powerfailure(0)
for(var/datum/computer_file/program/PRG in idle_threads)
@@ -400,6 +464,9 @@
power_usage += H.power_usage
if(battery_module)
+ if(!battery_module.check_functionality())
+ power_failure(1)
+ return
battery_module.battery.use(power_usage * CELLRATE)
last_power_usage = power_usage
@@ -421,10 +488,9 @@
user << "You insert \the [I] into \the [src]."
return
if(istype(W, /obj/item/weapon/paper))
- var/obj/item/weapon/paper/P = W
if(!nano_printer)
return
- nano_printer.load_paper(P)
+ nano_printer.attackby(W, user)
if(istype(W, /obj/item/weapon/computer_hardware))
var/obj/item/weapon/computer_hardware/C = W
if(C.hardware_size <= max_hardware_size)
@@ -441,6 +507,21 @@
relay_qdel()
qdel(src)
return
+ if(istype(W, /obj/item/weapon/weldingtool))
+ var/obj/item/weapon/weldingtool/WT = W
+ if(!WT.isOn())
+ user << "\The [W] is off."
+ return
+
+ if(!damage)
+ user << "\The [src] does not require repairs."
+ return
+
+ user << "You begin repairing damage to \the [src]..."
+ if(WT.remove_fuel(round(damage/75)) && do_after(usr, damage/10))
+ damage = 0
+ user << "You repair \the [src]."
+ return
if(W.is_screwdriver())
var/list/all_components = get_all_components()
@@ -551,13 +632,14 @@
found = 1
critical = 1
if(found)
- user << "You remove \the [H] from \the [src]."
+ if(user)
+ user << "You remove \the [H] from \the [src]."
H.forceMove(get_turf(src))
H.holder2 = null
if(critical && enabled)
- user << "\The [src]'s screen freezes for few seconds and then displays an \"HARDWARE ERROR: Critical component disconnected. Please verify component connection and reboot the device. If the problem persists contact technical support for assistance.\" warning."
- kill_program(1)
- enabled = 0
+ if(user)
+ user << "\The [src]'s screen freezes for few seconds and then displays an \"HARDWARE ERROR: Critical component disconnected. Please verify component connection and reboot the device. If the problem persists contact technical support for assistance.\" warning."
+ shutdown_computer()
update_icon()
@@ -607,16 +689,16 @@
SSnanoui.update_uis(src)
/obj/item/modular_computer/proc/check_update_ui_need()
- var/ui_updated_needed = 0
+ var/ui_update_needed = 0
if(battery_module)
var/batery_percent = battery_module.battery.percent()
- if(last_battery_percent != batery_percent) //Let's update UI on percent chandge
- ui_updated_needed = 1
+ if(last_battery_percent != batery_percent) //Let's update UI on percent change
+ ui_update_needed = 1
last_battery_percent = batery_percent
if(stationtime2text() != last_world_time)
last_world_time = stationtime2text()
- ui_updated_needed = 1
+ ui_update_needed = 1
if(idle_threads.len)
var/list/current_header_icons = list()
@@ -629,13 +711,51 @@
else if(!listequal(last_header_icons, current_header_icons))
last_header_icons = current_header_icons
- ui_updated_needed = 1
+ ui_update_needed = 1
else
for(var/x in last_header_icons|current_header_icons)
if(last_header_icons[x]!=current_header_icons[x])
last_header_icons = current_header_icons
- ui_updated_needed = 1
+ ui_update_needed = 1
break
- if(ui_updated_needed)
- update_uis()
\ No newline at end of file
+ if(ui_update_needed)
+ update_uis()
+
+/obj/item/modular_computer/proc/take_damage(var/amount, var/component_probability, var/damage_casing = 1, var/randomize = 1)
+ if(randomize)
+ // 75%-125%, rand() works with integers, apparently.
+ amount *= (rand(75, 125) / 100.0)
+ amount = round(amount)
+ if(damage_casing)
+ damage += amount
+ damage = between(0, damage, max_damage)
+
+ if(component_probability)
+ for(var/obj/item/weapon/computer_hardware/H in get_all_components())
+ if(prob(component_probability))
+ H.take_damage(round(amount / 2))
+
+ if(damage >= max_damage)
+ break_apart()
+
+// Stronger explosions cause serious damage to internal components
+// Minor explosions are mostly mitigitated by casing.
+/obj/item/modular_computer/ex_act(var/severity)
+ take_damage(rand(100,200) / severity, 30 / severity)
+
+// EMPs are similar to explosions, but don't cause physical damage to the casing. Instead they screw up the components
+/obj/item/modular_computer/emp_act(var/severity)
+ take_damage(rand(100,200) / severity, 50 / severity, 0)
+
+// "Stun" weapons can cause minor damage to components (short-circuits?)
+// "Burn" damage is equally strong against internal components and exterior casing
+// "Brute" damage mostly damages the casing.
+/obj/item/modular_computer/bullet_act(var/obj/item/projectile/Proj)
+ switch(Proj.damage_type)
+ if(BRUTE)
+ take_damage(Proj.damage, Proj.damage / 2)
+ if(HALLOSS)
+ take_damage(Proj.damage, Proj.damage / 3, 0)
+ if(BURN)
+ take_damage(Proj.damage, Proj.damage / 1.5)
\ No newline at end of file
diff --git a/code/modules/modular_computers/computers/item/processor.dm b/code/modules/modular_computers/computers/item/processor.dm
index 26d65bf31a..5e406d048c 100644
--- a/code/modules/modular_computers/computers/item/processor.dm
+++ b/code/modules/modular_computers/computers/item/processor.dm
@@ -11,10 +11,10 @@
var/obj/machinery/modular_computer/machinery_computer = null
/obj/item/modular_computer/processor/Destroy()
+ . = ..()
if(machinery_computer && (machinery_computer.cpu == src))
machinery_computer.cpu = null
machinery_computer = null
- return ..()
// Due to how processes work, we'd receive two process calls - one from machinery type and one from our own type.
// Since we want this to be in-sync with machinery (as it's hidden type for machinery-based computers) we'll ignore
@@ -25,6 +25,12 @@
else
return
+/obj/item/modular_computer/processor/examine(var/mob/user)
+ if(damage > broken_damage)
+ user << "It is heavily damaged!"
+ else if(damage)
+ user << "It is damaged."
+
// Power interaction is handled by our machinery part, due to machinery having APC connection.
/obj/item/modular_computer/processor/handle_power()
if(machinery_computer)
@@ -40,6 +46,8 @@
hardware_flag = machinery_computer.hardware_flag
max_hardware_size = machinery_computer.max_hardware_size
steel_sheet_cost = machinery_computer.steel_sheet_cost
+ max_damage = machinery_computer._max_damage
+ broken_damage = machinery_computer._break_damage
/obj/item/modular_computer/processor/relay_qdel()
qdel(machinery_computer)
@@ -110,7 +118,7 @@
/obj/item/modular_computer/processor/get_all_components()
var/list/all_components = ..()
- if(machinery_computer.tesla_link)
+ if(machinery_computer && machinery_computer.tesla_link)
all_components.Add(machinery_computer.tesla_link)
return all_components
diff --git a/code/modules/modular_computers/computers/item/tablet.dm b/code/modules/modular_computers/computers/item/tablet.dm
index 1c997202db..2154b83e54 100644
--- a/code/modules/modular_computers/computers/item/tablet.dm
+++ b/code/modules/modular_computers/computers/item/tablet.dm
@@ -6,4 +6,5 @@
icon_state_menu = "menu"
hardware_flag = PROGRAM_TABLET
max_hardware_size = 1
- w_class = 2
\ No newline at end of file
+ w_class = 2
+ light_strength = 2 // Same as PDAs
\ 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 21f040074e..65e81f0ad6 100644
--- a/code/modules/modular_computers/computers/machinery/modular_computer.dm
+++ b/code/modules/modular_computers/computers/machinery/modular_computer.dm
@@ -20,10 +20,13 @@
var/screen_icon_screensaver = "standby" // Icon state overlay when the computer is powered, but not 'switched on'.
var/max_hardware_size = 0 // Maximal hardware size. Currently, tablets have 1, laptops 2 and consoles 3. Limits what hardware types can be installed.
var/steel_sheet_cost = 10 // Amount of steel sheets refunded when disassembling an empty frame of this computer.
-
+ var/light_strength = 0 // Light luminosity when turned on
var/base_active_power_usage = 100 // Power usage when the computer is open (screen is active) and can be interacted with. Remember hardware can use power too.
var/base_idle_power_usage = 10 // Power usage when the computer is idle and screen is off (currently only applies to laptops)
+ var/_max_damage = 100
+ var/_break_damage = 50
+
var/obj/item/weapon/computer_hardware/tesla_link/tesla_link // Tesla Link component of this computer. Allows remote charging from nearest APC.
var/obj/item/modular_computer/processor/cpu = null // CPU that handles most logic while this type only handles power and other specific things.
@@ -42,7 +45,9 @@
if(!cpu || !cpu.enabled)
if (!(stat & NOPOWER) || battery_powered)
overlays.Add(screen_icon_screensaver)
+ set_light(0)
return
+ set_light(light_strength)
if(cpu.active_program)
overlays.Add(cpu.active_program.program_icon_state ? cpu.active_program.program_icon_state : screen_icon_state_menu)
else
@@ -57,15 +62,35 @@
if(cpu)
cpu.eject_id()
+// Eject ID card from computer, if it has ID slot with card inside.
+/obj/machinery/modular_computer/verb/eject_usb()
+ set name = "Eject Portable Device"
+ set category = "Object"
+ set src in view(1)
+
+ if(cpu)
+ cpu.eject_usb()
+
/obj/machinery/modular_computer/New()
..()
cpu = new(src)
+/obj/machinery/modular_computer/Destroy()
+ if(cpu)
+ qdel(cpu)
+ cpu = null
+ return ..()
+
// On-click handling. Turns on the computer if it's off and opens the GUI.
/obj/machinery/modular_computer/attack_hand(mob/user)
if(cpu)
cpu.attack_self(user) // CPU is an item, that's why we route attack_hand to attack_self
+/obj/machinery/modular_computer/examine(var/mob/user)
+ . = ..()
+ if(cpu)
+ cpu.examine(user)
+
// Process currently calls handle_power(), may be expanded in future if more things are added.
/obj/machinery/modular_computer/process()
if(cpu)
@@ -80,9 +105,9 @@
return null
// Used in following function to reduce copypaste
-/obj/machinery/modular_computer/proc/power_failure()
+/obj/machinery/modular_computer/proc/power_failure(var/malfunction = 0)
if(cpu && cpu.enabled) // Shut down the computer
- visible_message("\The [src]'s screen flickers [cpu.battery_module ? "\"BATTERY CRITICAL\"" : "\"EXTERNAL POWER LOSS\""] warning as it shuts down unexpectedly.")
+ visible_message("\The [src]'s screen flickers [cpu.battery_module ? "\"BATTERY [malfunction ? "MALFUNCTION" : "CRITICAL"]\"" : "\"EXTERNAL POWER LOSS\""] warning as it shuts down unexpectedly.")
if(cpu)
cpu.shutdown_computer(0)
battery_powered = 0
@@ -94,7 +119,7 @@
if(cpu.battery_module && cpu.battery_module.battery.charge <= 0) // Battery-run but battery is depleted.
power_failure()
return 0
- else if(!cpu.battery_module && (!powered() || !tesla_link || !tesla_link.enabled)) // Not battery run, but lacking APC connection.
+ else if(!cpu.battery_module && (!powered() || !tesla_link || !tesla_link.enabled || !tesla_link.check_functionality())) // Not battery run, but lacking APC connection.
power_failure()
return 0
else if(stat & NOPOWER)
@@ -111,7 +136,7 @@
power_usage += CH.power_usage
// Wireless APC connection exists.
- if(tesla_link && tesla_link.enabled)
+ if(tesla_link && tesla_link.enabled && tesla_link.check_functionality())
idle_power_usage = power_usage
active_power_usage = idle_power_usage + 100 // APCLink only charges at 100W rate, but covers any power usage.
use_power = 1
@@ -127,6 +152,9 @@
else // No wireless connection run only on battery.
use_power = 0
if (cpu.battery_module)
+ if(!cpu.battery_module.check_functionality())
+ power_failure(1)
+ return
cpu.battery_module.battery.use(power_usage * CELLRATE)
cpu.last_power_usage = power_usage
@@ -141,4 +169,25 @@
/obj/machinery/modular_computer/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
if(cpu)
return cpu.attackby(W, user)
- return ..()
\ No newline at end of file
+ return ..()
+
+
+// Stronger explosions cause serious damage to internal components
+// Minor explosions are mostly mitigitated by casing.
+/obj/machinery/modular_computer/ex_act(var/severity)
+ if(cpu)
+ cpu.ex_act(severity)
+
+// EMPs are similar to explosions, but don't cause physical damage to the casing. Instead they screw up the components
+/obj/machinery/modular_computer/emp_act(var/severity)
+ if(cpu)
+ cpu.emp_act(severity)
+
+// "Stun" weapons can cause minor damage to components (short-circuits?)
+// "Burn" damage is equally strong against internal components and exterior casing
+// "Brute" damage mostly damages the casing.
+/obj/machinery/modular_computer/bullet_act(var/obj/item/projectile/Proj)
+ if(cpu)
+ cpu.bullet_act(Proj)
+
+
diff --git a/code/modules/modular_computers/computers/machinery/modular_console.dm b/code/modules/modular_computers/computers/machinery/modular_console.dm
index 879b675c1f..9919df7820 100644
--- a/code/modules/modular_computers/computers/machinery/modular_console.dm
+++ b/code/modules/modular_computers/computers/machinery/modular_console.dm
@@ -14,6 +14,9 @@
base_active_power_usage = 500
max_hardware_size = 3
steel_sheet_cost = 20
+ light_strength = 4
+ _max_damage = 300
+ _break_damage = 150
/obj/machinery/modular_computer/console/buildable/New()
..()
diff --git a/code/modules/modular_computers/computers/machinery/modular_laptop.dm b/code/modules/modular_computers/computers/machinery/modular_laptop.dm
index ff2e851dc6..bce2d5192d 100644
--- a/code/modules/modular_computers/computers/machinery/modular_laptop.dm
+++ b/code/modules/modular_computers/computers/machinery/modular_laptop.dm
@@ -60,6 +60,9 @@
base_idle_power_usage = 25
base_active_power_usage = 200
max_hardware_size = 2
+ light_strength = 3
+ _max_damage = 200
+ _break_damage = 100
/obj/machinery/modular_computer/laptop/buildable/New()
..()
diff --git a/code/modules/modular_computers/hardware/battery_module.dm b/code/modules/modular_computers/hardware/battery_module.dm
index ae685c4b37..1443059868 100644
--- a/code/modules/modular_computers/hardware/battery_module.dm
+++ b/code/modules/modular_computers/hardware/battery_module.dm
@@ -5,7 +5,7 @@
desc = "A standard power cell, commonly seen in high-end portable microcomputers or low-end laptops. It's rating is 750."
icon_state = "battery_normal"
critical = 1
-
+ malfunction_probability = 1
var/battery_rating = 750
var/obj/item/weapon/cell/battery = null
@@ -50,7 +50,9 @@
hardware_size = 1
battery_rating = 1000000
-
+/obj/item/weapon/computer_hardware/battery_module/diagnostics(var/mob/user)
+ ..()
+ user << "Internal battery charge: [battery.charge]/[battery.maxcharge] CU"
/obj/item/weapon/computer_hardware/battery_module/New()
battery = new/obj/item/weapon/cell(src)
diff --git a/code/modules/modular_computers/hardware/hard_drive.dm b/code/modules/modular_computers/hardware/hard_drive.dm
index e595c56800..8dbf4e5be0 100644
--- a/code/modules/modular_computers/hardware/hard_drive.dm
+++ b/code/modules/modular_computers/hardware/hard_drive.dm
@@ -49,6 +49,12 @@
icon_state = "hdd_micro"
hardware_size = 1
+/obj/item/weapon/computer_hardware/hard_drive/diagnostics(var/mob/user)
+ ..()
+ // 999 is a byond limit that is in place. It's unlikely someone will reach that many files anyway, since you would sooner run out of space.
+ user << "NT-NFS File Table Status: [stored_files.len]/999"
+ user << "Storage capacity: [used_capacity]/[max_capacity]GQ"
+
// Use this proc to add file to the drive. Returns 1 on success and 0 on failure. Contains necessary sanity checks.
/obj/item/weapon/computer_hardware/hard_drive/proc/store_file(var/datum/computer_file/F)
if(!F || !istype(F))
@@ -57,6 +63,9 @@
if(!can_store_file(F.size))
return 0
+ if(!check_functionality())
+ return 0
+
if(!stored_files)
return 0
@@ -84,6 +93,9 @@
if(!stored_files)
return 0
+ if(!check_functionality())
+ return 0
+
if(F in stored_files)
stored_files -= F
recalculate_size()
@@ -124,6 +136,9 @@
// Tries to find the file by filename. Returns null on failure
/obj/item/weapon/computer_hardware/hard_drive/proc/find_file_by_name(var/filename)
+ if(!check_functionality())
+ return null
+
if(!filename)
return null
diff --git a/code/modules/modular_computers/hardware/hardware.dm b/code/modules/modular_computers/hardware/hardware.dm
index 580d73745b..43c7dbc4dc 100644
--- a/code/modules/modular_computers/hardware/hardware.dm
+++ b/code/modules/modular_computers/hardware/hardware.dm
@@ -3,12 +3,51 @@
desc = "Unknown Hardware"
icon = 'icons/obj/modular_components.dmi'
var/obj/item/modular_computer/holder2 = null
- var/power_usage = 0 // If the hardware uses extra power, change this.
- var/enabled = 1 // If the hardware is turned off set this to 0.
- var/critical = 1 // Prevent disabling for important component, like the HDD.
- var/hardware_size = 1 // Limits which devices can contain this component. 1: Tablets/Laptops/Consoles, 2: Laptops/Consoles, 3: Consoles only
+ var/power_usage = 0 // If the hardware uses extra power, change this.
+ var/enabled = 1 // If the hardware is turned off set this to 0.
+ var/critical = 1 // Prevent disabling for important component, like the HDD.
+ var/hardware_size = 1 // Limits which devices can contain this component. 1: Tablets/Laptops/Consoles, 2: Laptops/Consoles, 3: Consoles only
+ var/damage = 0 // Current damage level
+ var/max_damage = 100 // Maximal damage level.
+ var/damage_malfunction = 20 // "Malfunction" threshold. When damage exceeds this value the hardware piece will semi-randomly fail and do !!FUN!! things
+ var/damage_failure = 50 // "Failure" threshold. When damage exceeds this value the hardware piece will not work at all.
+ var/malfunction_probability = 10// Chance of malfunction when the component is damaged
+
+/obj/item/weapon/computer_hardware/attackby(var/obj/item/W as obj, var/mob/living/user as mob)
+ // Multitool. Runs diagnostics
+ if(istype(W, /obj/item/device/multitool))
+ user << "***** DIAGNOSTICS REPORT *****"
+ diagnostics(user)
+ user << "******************************"
+ return 1
+ // Nanopaste. Repair all damage if present for a single unit.
+ var/obj/item/stack/S = W
+ if(istype(S, /obj/item/stack/nanopaste))
+ if(!damage)
+ user << "\The [src] doesn't seem to require repairs."
+ return 1
+ if(S.use(1))
+ user << "You apply a bit of \the [W] to \the [src]. It immediately repairs all damage."
+ damage = 0
+ return 1
+ // Cable coil. Works as repair method, but will probably require multiple applications and more cable.
+ if(istype(S, /obj/item/stack/cable_coil))
+ if(!damage)
+ user << "\The [src] doesn't seem to require repairs."
+ return 1
+ if(S.use(1))
+ user << "You patch up \the [src] with a bit of \the [W]."
+ take_damage(-10)
+ return 1
+ return ..()
+
+
+// Called on multitool click, prints diagnostic information to the user.
+/obj/item/weapon/computer_hardware/proc/diagnostics(var/mob/user)
+ user << "Hardware Integrity Test... (Corruption: [damage]/[max_damage]) [damage > damage_failure ? "FAIL" : damage > damage_malfunction ? "WARN" : "PASS"]"
/obj/item/weapon/computer_hardware/New(var/obj/L)
+ w_class = hardware_size
if(istype(L, /obj/machinery/modular_computer))
var/obj/machinery/modular_computer/C = L
if(C.cpu)
@@ -20,4 +59,30 @@
/obj/item/weapon/computer_hardware/Destroy()
holder2 = null
- ..()
\ No newline at end of file
+ return ..()
+
+// Handles damage checks
+/obj/item/weapon/computer_hardware/proc/check_functionality()
+ // Too damaged to work at all.
+ if(damage > damage_failure)
+ return 0
+ // Still working. Well, sometimes...
+ if(damage > damage_malfunction)
+ if(prob(malfunction_probability))
+ return 0
+ // Good to go.
+ return 1
+
+/obj/item/weapon/computer_hardware/examine(var/mob/user)
+ . = ..()
+ if(damage > damage_failure)
+ user << "It seems to be severely damaged!"
+ else if(damage > damage_malfunction)
+ user << "It seems to be damaged!"
+ else if(damage)
+ user << "It seems to be slightly damaged."
+
+// Damages the component. Contains necessary checks. Negative damage "heals" the component.
+/obj/item/weapon/computer_hardware/proc/take_damage(var/amount)
+ damage += round(amount) // We want nice rounded numbers here.
+ damage = between(0, damage, max_damage) // Clamp the value.
diff --git a/code/modules/modular_computers/hardware/nano_printer.dm b/code/modules/modular_computers/hardware/nano_printer.dm
index 000c1c0981..11caa79794 100644
--- a/code/modules/modular_computers/hardware/nano_printer.dm
+++ b/code/modules/modular_computers/hardware/nano_printer.dm
@@ -1,27 +1,32 @@
/obj/item/weapon/computer_hardware/nano_printer
name = "nano printer"
- desc = "Small integrated printer with scanner and paper recycling module."
+ desc = "Small integrated printer with paper recycling module."
power_usage = 50
critical = 0
icon_state = "printer"
hardware_size = 1
var/stored_paper = 5
var/max_paper = 10
- var/obj/item/weapon/paper/P = null // Currently stored paper for scanning.
+/obj/item/weapon/computer_hardware/nano_printer/diagnostics(var/mob/user)
+ ..()
+ user << "Paper buffer level: [stored_paper]/[max_paper]"
/obj/item/weapon/computer_hardware/nano_printer/proc/print_text(var/text_to_print, var/paper_title = null)
if(!stored_paper)
return 0
+ if(!enabled)
+ return 0
+ if(!check_functionality())
+ return 0
- // Recycle stored paper
- if(P)
- stored_paper++
- qdel(P)
- P = null
+ var/obj/item/weapon/paper/P = new/obj/item/weapon/paper(get_turf(holder2))
- P = new/obj/item/weapon/paper(get_turf(holder2))
- P.info = text_to_print
+ // Damaged printer causes the resulting paper to be somewhat harder to read.
+ if(damage > damage_malfunction)
+ P.info = stars(text_to_print, 100-malfunction_probability)
+ else
+ P.info = text_to_print
if(paper_title)
P.name = paper_title
P.update_icon()
@@ -29,34 +34,18 @@
P = null
return 1
-/obj/item/weapon/computer_hardware/nano_printer/proc/load_paper(var/obj/item/weapon/paper/paper)
- if(!paper || !istype(paper))
- return 0
+/obj/item/weapon/computer_hardware/nano_printer/attackby(obj/item/W as obj, mob/user as mob)
+ if(istype(W, /obj/item/weapon/paper))
+ if(stored_paper >= max_paper)
+ user << "You try to add \the [W] into [src], but it's paper bin is full"
+ return
- // We already have paper loaded, recycle it.
- if(P && try_recycle_paper())
- P = paper
- P.forceMove(holder2)
-
-/obj/item/weapon/computer_hardware/nano_printer/proc/try_recycle_paper()
- if(!P)
- return 0
-
- if(stored_paper >= max_paper)
- return 0
-
- qdel(P)
- P = null
- return 1
+ user << "You insert \the [W] into [src]."
+ qdel(W)
+ stored_paper++
/obj/item/weapon/computer_hardware/nano_printer/Destroy()
if(holder2 && (holder2.nano_printer == src))
holder2.nano_printer = null
- if(P)
- if(holder2)
- P.forceMove(get_turf(holder2))
- else
- qdel(P)
- P = null
holder2 = null
..()
\ No newline at end of file
diff --git a/code/modules/modular_computers/hardware/network_card.dm b/code/modules/modular_computers/hardware/network_card.dm
index 1640105865..247508806e 100644
--- a/code/modules/modular_computers/hardware/network_card.dm
+++ b/code/modules/modular_computers/hardware/network_card.dm
@@ -11,6 +11,18 @@ var/global/ntnet_card_uid = 1
var/identification_string = "" // Identification string, technically nickname seen in the network. Can be set by user.
var/long_range = 0
var/ethernet = 0 // Hard-wired, therefore always on, ignores NTNet wireless checks.
+ malfunction_probability = 1
+
+/obj/item/weapon/computer_hardware/network_card/diagnostics(var/mob/user)
+ ..()
+ user << "NIX Unique ID: [identification_id]"
+ user << "NIX User Tag: [identification_string]"
+ user << "Supported protocols:"
+ user << "511.m SFS (Subspace) - Standard Frequency Spread"
+ if(long_range)
+ user << "511.n WFS/HB (Subspace) - Wide Frequency Spread/High Bandiwdth"
+ if(ethernet)
+ user << "OpenEth (Physical Connection) - Physical network connection port"
/obj/item/weapon/computer_hardware/network_card/New(var/l)
..(l)
@@ -27,7 +39,7 @@ var/global/ntnet_card_uid = 1
/obj/item/weapon/computer_hardware/network_card/wired
name = "wired NTNet network card"
- desc = "An advanced network card for usage with NTNet. This one uses wired connection."
+ desc = "An advanced network card for usage with standard NTNet frequencies. This one also supports wired connection."
ethernet = 1
power_usage = 100 // Better range but higher power usage.
icon_state = "netcard_ethernet"
@@ -51,6 +63,9 @@ var/global/ntnet_card_uid = 1
if(!enabled)
return 0
+ if(!check_functionality())
+ return 0
+
if(ethernet) // Computer is connected via wired connection.
return 3
@@ -60,7 +75,11 @@ var/global/ntnet_card_uid = 1
if(holder2)
var/turf/T = get_turf(holder2)
if((T && istype(T)) && T.z in using_map.station_levels)
- return 2
+ // Computer is on station. Low/High signal depending on what type of network card you have
+ if(long_range)
+ return 2
+ else
+ return 1
if(long_range) // Computer is not on station, but it has upgraded network card. Low signal.
return 1
diff --git a/code/modules/modular_computers/hardware/processor_unit.dm b/code/modules/modular_computers/hardware/processor_unit.dm
index c258a3e5aa..fdaf216298 100644
--- a/code/modules/modular_computers/hardware/processor_unit.dm
+++ b/code/modules/modular_computers/hardware/processor_unit.dm
@@ -8,6 +8,7 @@
hardware_size = 2
power_usage = 50
critical = 1
+ malfunction_probability = 1
var/max_idle_programs = 2 // 2 idle, + 1 active = 3 as said in description.