Modular Cmp Updates

This commit is contained in:
Letter N
2021-02-12 18:29:00 +08:00
parent 5db87b9065
commit 5b0a1077f4
46 changed files with 1311 additions and 318 deletions
@@ -48,8 +48,8 @@
var/multiple_slots = istype(card_slot) && istype(card_slot2)
if(card_slot)
if(card_slot?.stored_card || card_slot2?.stored_card)
var/obj/item/card/id/first_ID = card_slot.stored_card
var/obj/item/card/id/second_ID = card_slot2.stored_card
var/obj/item/card/id/first_ID = card_slot?.stored_card
var/obj/item/card/id/second_ID = card_slot2?.stored_card
var/multiple_cards = istype(first_ID) && istype(second_ID)
if(user_is_adjacent)
. += "It has [multiple_slots ? "two slots" : "a slot"] for identification cards installed[multiple_cards ? " which contain [first_ID] and [second_ID]" : ", one of which contains [first_ID ? first_ID : second_ID]"]."
@@ -20,6 +20,10 @@
var/last_battery_percent = 0 // Used for deciding if battery percentage has chandged
var/last_world_time = "00:00"
var/list/last_header_icons
///Looping sound for when the computer is on
var/datum/looping_sound/computer/soundloop
///Whether or not this modular computer uses the looping sound
var/looping_sound = TRUE
var/base_active_power_usage = 50 // 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 = 5 // Power usage when the computer is idle and screen is off (currently only applies to laptops)
@@ -56,11 +60,14 @@
physical = src
comp_light_color = "#FFFFFF"
idle_threads = list()
if(looping_sound)
soundloop = new(list(src), enabled)
update_icon()
/obj/item/modular_computer/Destroy()
kill_program(forced = TRUE)
STOP_PROCESSING(SSobj, src)
QDEL_NULL(soundloop)
for(var/H in all_components)
var/obj/item/computer_hardware/CH = all_components[H]
if(CH.holder == src)
@@ -103,7 +110,6 @@
var/obj/item/computer_hardware/card_slot/card_slot = all_components[MC_CARD]
var/obj/item/computer_hardware/card_slot/card_slot2 = all_components[MC_CARD2]
if(!(card_slot || card_slot2))
//to_chat(user, "<span class='warning'>There isn't anywhere you can fit a card into on this computer.</span>")
return FALSE
var/obj/item/card/inserting_id = inserting_item.RemoveID()
@@ -112,7 +118,6 @@
if((card_slot?.try_insert(inserting_id)) || (card_slot2?.try_insert(inserting_id)))
return TRUE
//to_chat(user, "<span class='warning'>This computer doesn't have an open card slot.</span>")
return FALSE
/obj/item/modular_computer/MouseDrop(obj/over_object, src_location, over_location)
@@ -198,7 +203,7 @@
to_chat(user, "<span class='warning'>You send an activation signal to \the [src], but it responds with an error code. It must be damaged.</span>")
else
to_chat(user, "<span class='warning'>You press the power button, but the computer fails to boot up, displaying variety of errors before shutting down again.</span>")
return
return FALSE
// If we have a recharger, enable it automatically. Lets computer without a battery work.
var/obj/item/computer_hardware/recharger/recharger = all_components[MC_CHARGE]
@@ -210,24 +215,28 @@
to_chat(user, "<span class='notice'>You send an activation signal to \the [src], turning it on.</span>")
else
to_chat(user, "<span class='notice'>You press the power button and start up \the [src].</span>")
if(looping_sound)
soundloop.start()
enabled = 1
update_icon()
ui_interact(user)
return TRUE
else // Unpowered
if(issynth)
to_chat(user, "<span class='warning'>You send an activation signal to \the [src] but it does not respond.</span>")
else
to_chat(user, "<span class='warning'>You press the power button but \the [src] does not respond.</span>")
return FALSE
// Process currently calls handle_power(), may be expanded in future if more things are added.
/obj/item/modular_computer/process()
/obj/item/modular_computer/process(delta_time)
if(!enabled) // The computer is turned off
last_power_usage = 0
return 0
return
if(obj_integrity <= integrity_failure * max_integrity)
shutdown_computer()
return 0
return
if(active_program && active_program.requires_ntnet && !get_ntnet_status(active_program.requires_ntnet_feature))
active_program.event_networkfailure(0) // Active program requires NTNet to run but we've just lost connection. Crash.
@@ -239,7 +248,7 @@
if(active_program)
if(active_program.program_state != PROGRAM_STATE_KILLED)
active_program.process_tick()
active_program.process_tick(delta_time)
active_program.ntnet_status = get_ntnet_status()
else
active_program = null
@@ -247,14 +256,36 @@
for(var/I in idle_threads)
var/datum/computer_file/program/P = I
if(P.program_state != PROGRAM_STATE_KILLED)
P.process_tick()
P.process_tick(delta_time)
P.ntnet_status = get_ntnet_status()
else
idle_threads.Remove(P)
handle_power() // Handles all computer power interaction
handle_power(delta_time) // Handles all computer power interaction
//check_update_ui_need()
/**
* Displays notification text alongside a soundbeep when requested to by a program.
*
* After checking tha the requesting program is allowed to send an alert, creates
* a visible message of the requested text alongside a soundbeep. This proc adds
* text to indicate that the message is coming from this device and the program
* on it, so the supplied text should be the exact message and ending punctuation.
*
* Arguments:
* The program calling this proc.
* The message that the program wishes to display.
*/
/obj/item/modular_computer/proc/alert_call(datum/computer_file/program/caller, alerttext, sound = 'sound/machines/twobeep_high.ogg')
if(!caller || !caller.alert_able || caller.alert_silenced || !alerttext) //Yeah, we're checking alert_able. No, you don't get to make alerts that the user can't silence.
return
playsound(src, sound, 50, TRUE)
visible_message("<span class='notice'>The [src] displays a [caller.filedesc] notification: [alerttext]</span>")
var/mob/living/holder = loc
if(istype(holder))
to_chat(holder, "[icon2html(src)] <span class='notice'>The [src] displays a [caller.filedesc] notification: [alerttext]</span>")
// Function used by NanoUI's to obtain data for header. All relevant entries begin with "PC_"
/obj/item/modular_computer/proc/get_header_data()
var/list/data = list()
@@ -344,13 +375,76 @@
for(var/datum/computer_file/program/P in idle_threads)
P.kill_program(forced = TRUE)
idle_threads.Remove(P)
if(looping_sound)
soundloop.stop()
if(loud)
physical.visible_message("<span class='notice'>\The [src] shuts down.</span>")
enabled = 0
update_icon()
/**
* Toggles the computer's flashlight, if it has one.
*
* Called from ui_act(), does as the name implies.
* It is seperated from ui_act() to be overwritten as needed.
*/
/obj/item/modular_computer/proc/toggle_flashlight()
if(!has_light)
return FALSE
set_light_on(!light_on)
if(light_on)
set_light(comp_light_luminosity, 1, comp_light_color)
else
set_light(0)
return TRUE
/**
* Sets the computer's light color, if it has a light.
*
* Called from ui_act(), this proc takes a color string and applies it.
* It is seperated from ui_act() to be overwritten as needed.
* Arguments:
** color is the string that holds the color value that we should use. Proc auto-fails if this is null.
*/
/obj/item/modular_computer/proc/set_flashlight_color(color)
if(!has_light || !color)
return FALSE
comp_light_color = color
set_light_color(color)
update_light()
return TRUE
/obj/item/modular_computer/screwdriver_act(mob/user, obj/item/tool)
if(!all_components.len)
to_chat(user, "<span class='warning'>This device doesn't have any components installed.</span>")
return
var/list/component_names = list()
for(var/h in all_components)
var/obj/item/computer_hardware/H = all_components[h]
component_names.Add(H.name)
var/choice = input(user, "Which component do you want to uninstall?", "Computer maintenance", null) as null|anything in sortList(component_names)
if(!choice)
return
if(!Adjacent(user))
return
var/obj/item/computer_hardware/H = find_hardware_by_name(choice)
if(!H)
return
uninstall_component(H, user)
return
/obj/item/modular_computer/attackby(obj/item/W as obj, mob/user as mob)
// Check for ID first
if(istype(W, /obj/item/card/id) && InsertID(W))
return
// Insert items into the components
for(var/h in all_components)
var/obj/item/computer_hardware/H = all_components[h]
@@ -386,31 +480,6 @@
to_chat(user, "<span class='notice'>You repair \the [src].</span>")
return
if(W.tool_behaviour == TOOL_SCREWDRIVER)
if(!all_components.len)
to_chat(user, "<span class='warning'>This device doesn't have any components installed.</span>")
return
var/list/component_names = list()
for(var/h in all_components)
var/obj/item/computer_hardware/H = all_components[h]
component_names.Add(H.name)
var/choice = input(user, "Which component do you want to uninstall?", "Computer maintenance", null) as null|anything in sortList(component_names)
if(!choice)
return
if(!Adjacent(user))
return
var/obj/item/computer_hardware/H = find_hardware_by_name(choice)
if(!H)
return
uninstall_component(H, user)
return
..()
// Used by processor to relay qdel() to machinery type.
@@ -5,7 +5,7 @@
var/obj/item/computer_hardware/recharger/recharger = all_components[MC_CHARGE]
if(recharger && recharger.check_functionality())
if(recharger?.check_functionality())
if(recharger.use_power(amount))
return TRUE
@@ -22,7 +22,7 @@
/obj/item/modular_computer/proc/give_power(amount)
var/obj/item/computer_hardware/battery/battery_module = all_components[MC_CELL]
if(battery_module && battery_module.battery)
if(battery_module?.battery)
return battery_module.battery.give(amount)
return 0
@@ -41,10 +41,10 @@
shutdown_computer(0)
// Handles power-related things, such as battery interaction, recharging, shutdown when it's discharged
/obj/item/modular_computer/proc/handle_power()
/obj/item/modular_computer/proc/handle_power(delta_time)
var/obj/item/computer_hardware/recharger/recharger = all_components[MC_CHARGE]
if(recharger)
recharger.process()
recharger.process(delta_time)
var/power_usage = screen_on ? base_active_power_usage : base_idle_power_usage
@@ -7,17 +7,17 @@
if(!enabled)
if(ui)
ui.close()
return 0
return
if(!use_power())
if(ui)
ui.close()
return 0
return
// Robots don't really need to see the screen, their wireless connection works as long as computer is on.
if(!screen_on && !issilicon(user))
if(ui)
ui.close()
return 0
return
// If we have an active program switch to it now.
if(active_program)
@@ -37,8 +37,8 @@
if (!ui)
ui = new(user, src, "NtosMain")
ui.set_autoupdate(TRUE)
ui.open()
ui.send_asset(get_asset_datum(/datum/asset/simple/headers))
if(ui.open())
ui.send_asset(get_asset_datum(/datum/asset/simple/headers))
/obj/item/modular_computer/ui_data(mob/user)
@@ -47,7 +47,9 @@
data["login"] = list()
var/obj/item/computer_hardware/card_slot/cardholder = all_components[MC_CARD]
data["cardholder"] = FALSE
if(cardholder)
data["cardholder"] = TRUE
var/obj/item/card/id/stored_card = cardholder.GetID()
if(stored_card)
var/stored_name = stored_card.registered_name
@@ -74,11 +76,11 @@
data["programs"] = list()
var/obj/item/computer_hardware/hard_drive/hard_drive = all_components[MC_HDD]
for(var/datum/computer_file/program/P in hard_drive.stored_files)
var/running = 0
var/running = FALSE
if(P in idle_threads)
running = 1
running = TRUE
data["programs"] += list(list("name" = P.filename, "desc" = P.filedesc, "running" = running))
data["programs"] += list(list("name" = P.filename, "desc" = P.filedesc, "running" = running, "icon" = P.program_icon, "alert" = P.alert_pending))
data["has_light"] = has_light
data["light_on"] = light_on
@@ -88,8 +90,10 @@
// Handles user's GUI input
/obj/item/modular_computer/ui_act(action, params)
if(..())
. = ..()
if(.)
return
var/obj/item/computer_hardware/hard_drive/hard_drive = all_components[MC_HDD]
switch(action)
if("PC_exit")
@@ -144,6 +148,7 @@
if(P in idle_threads)
P.program_state = PROGRAM_STATE_ACTIVE
active_program = P
P.alert_pending = FALSE
idle_threads.Remove(P)
update_icon()
return
@@ -159,16 +164,12 @@
return
if(P.run_program(user))
active_program = P
P.alert_pending = FALSE
update_icon()
return 1
if("PC_toggle_light")
light_on = !light_on
if(light_on)
set_light(comp_light_luminosity, 1, comp_light_color)
else
set_light(0)
return TRUE
return toggle_flashlight()
if("PC_light_color")
var/mob/user = usr
@@ -180,10 +181,7 @@
if(color_hex2num(new_color) < 200) //Colors too dark are rejected
to_chat(user, "<span class='warning'>That color is too dark! Choose a lighter one.</span>")
new_color = null
comp_light_color = new_color
light_color = new_color
update_light()
return TRUE
return set_flashlight_color(new_color)
if("PC_Eject_Disk")
var/param = params["name"]
@@ -17,7 +17,7 @@
// No running around with open laptops in hands.
item_flags = SLOWS_WHILE_IN_HAND
screen_on = 0 // Starts closed
screen_on = FALSE // Starts closed
var/start_open = TRUE // unless this var is set to 1
var/icon_state_closed = "laptop-closed"
var/w_class_open = WEIGHT_CLASS_BULKY
@@ -64,17 +64,18 @@
. = ..()
if(over_object == usr || over_object == src)
try_toggle_open(usr)
else if(istype(over_object, /obj/screen/inventory/hand))
return
if(istype(over_object, /obj/screen/inventory/hand))
var/obj/screen/inventory/hand/H = over_object
var/mob/M = usr
if(!M.restrained() && !M.stat)
if(!isturf(loc) || !Adjacent(M))
return
M.put_in_hand(src, H.held_index)
if(M.stat != CONSCIOUS || M.restrained())
return
if(!isturf(loc) || !Adjacent(M))
return
M.put_in_hand(src, H.held_index)
/obj/item/modular_computer/laptop/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
/obj/item/modular_computer/laptop/on_attack_hand(mob/user)
if(screen_on && isturf(loc))
return attack_self(user)
@@ -43,13 +43,6 @@
/obj/item/modular_computer/processor/relay_qdel()
qdel(machinery_computer)
// This thing is not meant to be used on it's own, get topic data from our machinery owner.
//obj/item/modular_computer/processor/canUseTopic(atom/movable/M, be_close=FALSE, no_dexterity=FALSE, no_tk=FALSE)
// if(!machinery_computer)
// return 0
// return machinery_computer.canUseTopic(user, state)
/obj/item/modular_computer/processor/shutdown_computer()
if(!machinery_computer)
return
@@ -59,3 +52,9 @@
/obj/item/modular_computer/processor/attack_ghost(mob/user)
ui_interact(user)
/obj/item/modular_computer/processor/alert_call(datum/computer_file/program/caller, alerttext)
if(!caller || !caller.alert_able || caller.alert_silenced || !alerttext)
return
playsound(src, 'sound/machines/twobeep_high.ogg', 50, TRUE)
machinery_computer.visible_message("<span class='notice'>The [src] displays a [caller.filedesc] notification: [alerttext]</span>")
@@ -14,6 +14,7 @@
slot_flags = ITEM_SLOT_ID | ITEM_SLOT_BELT
has_light = TRUE //LED flashlight!
comp_light_luminosity = 2.3 //Same as the PDA
looping_sound = FALSE
var/has_variants = TRUE
var/finish_color = null
@@ -41,6 +42,7 @@
comp_light_luminosity = 6.3
has_variants = FALSE
device_theme = "syndicate"
light_color = COLOR_RED
/obj/item/modular_computer/tablet/nukeops/emag_act(mob/user)
if(!enabled)
@@ -48,3 +50,98 @@
return FALSE
to_chat(user, "<span class='notice'>You swipe \the [src]. It's screen briefly shows a message reading \"MEMORY CODE INJECTION DETECTED AND SUCCESSFULLY QUARANTINED\".</span>")
return FALSE
/// Borg Built-in tablet interface
/obj/item/modular_computer/tablet/integrated
name = "modular interface"
icon_state = "tablet-silicon"
has_light = FALSE //tablet light button actually enables/disables the borg lamp
comp_light_luminosity = 0
has_variants = FALSE
///Ref to the borg we're installed in. Set by the borg during our creation.
var/mob/living/silicon/robot/borgo
///Ref to the RoboTact app. Important enough to borgs to deserve a ref.
var/datum/computer_file/program/robotact/robotact
///IC log that borgs can view in their personal management app
var/list/borglog = list()
/obj/item/modular_computer/tablet/integrated/Initialize(mapload)
. = ..()
vis_flags |= VIS_INHERIT_ID
borgo = loc
if(!istype(borgo))
borgo = null
stack_trace("[type] initialized outside of a borg, deleting.")
return INITIALIZE_HINT_QDEL
/obj/item/modular_computer/tablet/integrated/Destroy()
borgo = null
return ..()
/obj/item/modular_computer/tablet/integrated/turn_on(mob/user)
if(borgo?.stat != DEAD)
return ..()
return FALSE
/**
* Returns a ref to the RoboTact app, creating the app if need be.
*
* The RoboTact app is important for borgs, and so should always be available.
* This proc will look for it in the tablet's robotact var, then check the
* hard drive if the robotact var is unset, and finally attempt to create a new
* copy if the hard drive does not contain the app. If the hard drive rejects
* the new copy (such as due to lack of space), the proc will crash with an error.
* RoboTact is supposed to be undeletable, so these will create runtime messages.
*/
/obj/item/modular_computer/tablet/integrated/proc/get_robotact()
if(!borgo)
return null
if(!robotact)
var/obj/item/computer_hardware/hard_drive/hard_drive = all_components[MC_HDD]
robotact = hard_drive.find_file_by_name("robotact")
if(!robotact)
stack_trace("Cyborg [borgo] ( [borgo.type] ) was somehow missing their self-manage app in their tablet. A new copy has been created.")
robotact = new(hard_drive)
if(!hard_drive.store_file(robotact))
qdel(robotact)
robotact = null
CRASH("Cyborg [borgo]'s tablet hard drive rejected recieving a new copy of the self-manage app. To fix, check the hard drive's space remaining. Please make a bug report about this.")
return robotact
//Makes the light settings reflect the borg's headlamp settings
/obj/item/modular_computer/tablet/integrated/ui_data(mob/user)
. = ..()
.["has_light"] = TRUE
.["light_on"] = borgo?.lamp_enabled
.["comp_light_color"] = borgo?.lamp_color
//Makes the flashlight button affect the borg rather than the tablet
/obj/item/modular_computer/tablet/integrated/toggle_flashlight()
if(!borgo || QDELETED(borgo))
return FALSE
borgo.toggle_headlamp()
return TRUE
//Makes the flashlight color setting affect the borg rather than the tablet
/obj/item/modular_computer/tablet/integrated/set_flashlight_color(color)
if(!borgo || QDELETED(borgo) || !color)
return FALSE
borgo.lamp_color = color
borgo.toggle_headlamp(FALSE, TRUE)
return TRUE
/obj/item/modular_computer/tablet/integrated/alert_call(datum/computer_file/program/caller, alerttext, sound = 'sound/machines/twobeep_high.ogg')
if(!caller || !caller.alert_able || caller.alert_silenced || !alerttext) //Yeah, we're checking alert_able. No, you don't get to make alerts that the user can't silence.
return
borgo.playsound_local(src, sound, 50, TRUE)
to_chat(borgo, "<span class='notice'>The [src] displays a [caller.filedesc] notification: [alerttext]</span>")
/obj/item/modular_computer/tablet/integrated/syndicate
icon_state = "tablet-silicon-syndicate"
device_theme = "syndicate"
/obj/item/modular_computer/tablet/integrated/syndicate/Initialize()
. = ..()
borgo.lamp_color = COLOR_RED //Syndicate likes it red
@@ -29,8 +29,7 @@
install_component(new /obj/item/computer_hardware/card_slot)
install_component(new /obj/item/computer_hardware/network_card)
install_component(new /obj/item/computer_hardware/printer/mini)
hard_drive.store_file(new /datum/computer_file/program/bounty)
//hard_drive.store_file(new /datum/computer_file/program/shipping)
hard_drive.store_file(new /datum/computer_file/program/shipping)
/obj/item/modular_computer/tablet/preset/advanced/atmos/Initialize() //This will be defunct and will be replaced when NtOS PDAs are done
. = ..()
@@ -38,8 +37,10 @@
/obj/item/modular_computer/tablet/preset/advanced/command/Initialize()
. = ..()
var/obj/item/computer_hardware/hard_drive/small/hard_drive = find_hardware_by_name("solid state drive")
install_component(new /obj/item/computer_hardware/sensorpackage)
install_component(new /obj/item/computer_hardware/card_slot/secondary)
hard_drive.store_file(new /datum/computer_file/program/budgetorders)
/// Given by the syndicate as part of the contract uplink bundle - loads in the Contractor Uplink.
/obj/item/modular_computer/tablet/syndicate_contract_uplink/preset/uplink/Initialize()
@@ -67,3 +68,11 @@
install_component(new /obj/item/computer_hardware/battery(src, /obj/item/stock_parts/cell/computer))
install_component(new /obj/item/computer_hardware/hard_drive/small/nukeops)
install_component(new /obj/item/computer_hardware/network_card)
//Borg Built-in tablet
/obj/item/modular_computer/tablet/integrated/Initialize()
. = ..()
install_component(new /obj/item/computer_hardware/processor_unit/small)
install_component(new /obj/item/computer_hardware/hard_drive/small/integrated)
install_component(new /obj/item/computer_hardware/recharger/cyborg)
install_component(new /obj/item/computer_hardware/network_card/integrated)
@@ -48,7 +48,7 @@
cpu.attack_ghost(user)
/obj/machinery/modular_computer/emag_act(mob/user)
. = ..()
. = ..()
if(!cpu)
to_chat(user, "<span class='warning'>You'd need to turn the [src] on first.</span>")
return FALSE
@@ -59,7 +59,7 @@
icon_state = icon_state_powered
if(!cpu || !cpu.enabled)
if (!(stat & NOPOWER) && (cpu && cpu.use_power()))
if (!(stat & NOPOWER) && (cpu?.use_power()))
add_overlay(screen_icon_screensaver)
else
icon_state = icon_state_unpowered
@@ -88,16 +88,16 @@
return ..()
// Process currently calls handle_power(), may be expanded in future if more things are added.
/obj/machinery/modular_computer/process()
/obj/machinery/modular_computer/process(delta_time)
if(cpu)
// Keep names in sync.
cpu.name = name
cpu.process()
cpu.process(delta_time)
// Used in following function to reduce copypaste
/obj/machinery/modular_computer/proc/power_failure(malfunction = 0)
var/obj/item/computer_hardware/battery/battery_module = cpu.all_components[MC_CELL]
if(cpu && cpu.enabled) // Shut down the computer
if(cpu?.enabled) // Shut down the computer
visible_message("<span class='danger'>\The [src]'s screen flickers [battery_module ? "\"BATTERY [malfunction ? "MALFUNCTION" : "CRITICAL"]\"" : "\"EXTERNAL POWER LOSS\""] warning as it shuts down unexpectedly.</span>")
if(cpu)
cpu.shutdown_computer(0)
@@ -106,14 +106,18 @@
// 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()
if(cpu && cpu.use_power()) // If MC_CPU still has a power source, PC wouldn't go offline.
if(cpu?.use_power()) // If MC_CPU still has a power source, PC wouldn't go offline.
stat &= ~NOPOWER
update_icon()
return
. = ..()
/obj/machinery/modular_computer/screwdriver_act(mob/user, obj/item/tool)
if(cpu)
return cpu.screwdriver_act(user, tool)
/obj/machinery/modular_computer/attackby(obj/item/W as obj, mob/user)
if(cpu && !(flags_1 & NODECONSTRUCT_1))
if (user.a_intent == INTENT_HELP && cpu && !(flags_1 & NODECONSTRUCT_1))
return cpu.attackby(W, user)
return ..()
@@ -125,11 +129,11 @@
cpu.ex_act(severity)
// switch(severity)
// if(EXPLODE_DEVASTATE)
// SSexplosions.highobj += cpu
// SSexplosions.high_mov_atom += cpu
// if(EXPLODE_HEAVY)
// SSexplosions.medobj += cpu
// SSexplosions.med_mov_atom += cpu
// if(EXPLODE_LIGHT)
// SSexplosions.lowobj += cpu
// SSexplosions.low_mov_atom += cpu
..()
// EMPs are similar to explosions, but don't cause physical damage to the casing. Instead they screw up the components
@@ -37,7 +37,7 @@
var/obj/item/computer_hardware/network_card/wired/network_card = new()
cpu.install_component(network_card)
cpu.install_component(new /obj/item/computer_hardware/recharger/APC)
cpu.install_component(new /obj/item/computer_hardware/recharger/apc_recharger)
cpu.install_component(new /obj/item/computer_hardware/hard_drive/super) // Consoles generally have better HDDs due to lower space limitations
var/area/A = get_area(src)