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.