diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm index c7afad3cb6f..8f24ecfc84d 100644 --- a/code/game/machinery/recharger.dm +++ b/code/game/machinery/recharger.dm @@ -7,8 +7,8 @@ use_power = 1 idle_power_usage = 4 active_power_usage = 250 - var/obj/item/weapon/charging = null - var/list/allowed_devices = list(/obj/item/weapon/gun/energy,/obj/item/weapon/melee/baton,/obj/item/ammo_box/magazine/recharge,/obj/item/weapon/computer_hardware/battery_module,/obj/item/laptop,/obj/item/modular_computer/) + var/obj/item/charging = null + var/list/allowed_devices = list(/obj/item/weapon/gun/energy,/obj/item/weapon/melee/baton,/obj/item/ammo_box/magazine/recharge,/obj/item/device/modular_computer) var/recharge_coeff = 1 /obj/machinery/recharger/New() @@ -37,9 +37,7 @@ playsound(loc, 'sound/items/Ratchet.ogg', 75, 1) return - var/allowed = 0 - for (var/allowed_type in allowed_devices) - if (istype(G, allowed_type)) allowed = 1 + var/allowed = is_type_in_list(G, allowed_devices) if(allowed) if(anchored) @@ -132,28 +130,10 @@ use_power(200 * recharge_coeff) using_power = 1 - if(istype(charging, /obj/item/laptop)) - var/obj/item/laptop/L = charging - if(L.stored_computer.cpu.battery_module) - var/obj/item/weapon/computer_hardware/battery_module/B = L.stored_computer.cpu.battery_module - if(B.battery) - if(B.battery.charge < B.battery.maxcharge) - B.battery.give(B.battery.chargerate * recharge_coeff) - use_power(200 * recharge_coeff) - using_power = 1 - - if(istype(charging, /obj/item/weapon/computer_hardware/battery_module)) - var/obj/item/weapon/computer_hardware/battery_module/B = charging - if(B.battery) - if(B.battery.charge < B.battery.maxcharge) - B.battery.give(B.battery.chargerate * recharge_coeff) - use_power(200 * recharge_coeff) - using_power = 1 - - if(istype(charging, /obj/item/modular_computer)) - var/obj/item/modular_computer/C = charging + if(istype(charging, /obj/item/device/modular_computer)) + var/obj/item/device/modular_computer/C = charging if(C.battery_module) - var/obj/item/weapon/computer_hardware/battery_module/B = C.battery_module + var/obj/item/weapon/computer_hardware/battery/B = C.battery_module if(B.battery) if(B.battery.charge < B.battery.maxcharge) B.battery.give(B.battery.chargerate * recharge_coeff) diff --git a/code/modules/jobs/job_types/captain.dm b/code/modules/jobs/job_types/captain.dm index 38705fb0391..f210c426630 100644 --- a/code/modules/jobs/job_types/captain.dm +++ b/code/modules/jobs/job_types/captain.dm @@ -99,7 +99,7 @@ Head of Personnel shoes = /obj/item/clothing/shoes/sneakers/brown head = /obj/item/clothing/head/hopcap backpack_contents = list(/obj/item/weapon/storage/box/ids=1,\ - /obj/item/weapon/melee/classic_baton/telescopic=1, /obj/item/modular_computer/tablet/preset/advanced = 1) + /obj/item/weapon/melee/classic_baton/telescopic=1, /obj/item/device/modular_computer/tablet/preset/advanced = 1) /datum/outfit/job/hop/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) ..() diff --git a/code/modules/jobs/job_types/cargo_service.dm b/code/modules/jobs/job_types/cargo_service.dm index adbdf9f6fa0..460d9da5299 100644 --- a/code/modules/jobs/job_types/cargo_service.dm +++ b/code/modules/jobs/job_types/cargo_service.dm @@ -228,4 +228,4 @@ Janitor belt = /obj/item/device/pda/janitor ears = /obj/item/device/radio/headset/headset_srv uniform = /obj/item/clothing/under/rank/janitor - backpack_contents = list(/obj/item/modular_computer/tablet/preset/advanced=1) + backpack_contents = list(/obj/item/device/modular_computer/tablet/preset/advanced=1) diff --git a/code/modules/jobs/job_types/engineering.dm b/code/modules/jobs/job_types/engineering.dm index 5ec3e6a4ced..eea162ee3ca 100644 --- a/code/modules/jobs/job_types/engineering.dm +++ b/code/modules/jobs/job_types/engineering.dm @@ -36,7 +36,7 @@ Chief Engineer shoes = /obj/item/clothing/shoes/sneakers/brown head = /obj/item/clothing/head/hardhat/white gloves = /obj/item/clothing/gloves/color/black/ce - backpack_contents = list(/obj/item/weapon/melee/classic_baton/telescopic=1,/obj/item/modular_computer/tablet/preset/advanced=1) + backpack_contents = list(/obj/item/weapon/melee/classic_baton/telescopic=1,/obj/item/device/modular_computer/tablet/preset/advanced=1) backpack = /obj/item/weapon/storage/backpack/industrial satchel = /obj/item/weapon/storage/backpack/satchel/eng @@ -89,7 +89,7 @@ Station Engineer dufflebag = /obj/item/weapon/storage/backpack/dufflebag/engineering box = /obj/item/weapon/storage/box/engineer pda_slot = slot_l_store - backpack_contents = list(/obj/item/modular_computer/tablet/preset/advanced=1) + backpack_contents = list(/obj/item/device/modular_computer/tablet/preset/advanced=1) /* Atmospheric Technician @@ -125,4 +125,4 @@ Atmospheric Technician dufflebag = /obj/item/weapon/storage/backpack/dufflebag/engineering box = /obj/item/weapon/storage/box/engineer pda_slot = slot_l_store - backpack_contents = list(/obj/item/modular_computer/tablet/preset/advanced=1) \ No newline at end of file + backpack_contents = list(/obj/item/device/modular_computer/tablet/preset/advanced=1) \ No newline at end of file diff --git a/code/modules/jobs/job_types/science.dm b/code/modules/jobs/job_types/science.dm index b52f8ac919a..f0ad16f3053 100644 --- a/code/modules/jobs/job_types/science.dm +++ b/code/modules/jobs/job_types/science.dm @@ -38,7 +38,7 @@ Research Director suit = /obj/item/clothing/suit/toggle/labcoat l_hand = /obj/item/weapon/clipboard l_pocket = /obj/item/device/laser_pointer - backpack_contents = list(/obj/item/weapon/melee/classic_baton/telescopic=1,/obj/item/modular_computer/tablet/preset/advanced=1) + backpack_contents = list(/obj/item/weapon/melee/classic_baton/telescopic=1,/obj/item/device/modular_computer/tablet/preset/advanced=1) backpack = /obj/item/weapon/storage/backpack/science satchel = /obj/item/weapon/storage/backpack/satchel/tox diff --git a/code/modules/modular_computers/NTNet/NTNet_relay.dm b/code/modules/modular_computers/NTNet/NTNet_relay.dm index 9cc0170d8de..e0b4be93d0a 100644 --- a/code/modules/modular_computers/NTNet/NTNet_relay.dm +++ b/code/modules/modular_computers/NTNet/NTNet_relay.dm @@ -42,6 +42,8 @@ else use_power = 1 + update_icon() + if(dos_overload) dos_overload = max(0, dos_overload - dos_dissipate) diff --git a/code/modules/modular_computers/computers/item/computer.dm b/code/modules/modular_computers/computers/item/computer.dm new file mode 100644 index 00000000000..71bfc52cfe4 --- /dev/null +++ b/code/modules/modular_computers/computers/item/computer.dm @@ -0,0 +1,418 @@ +// This is the base type that does all the hardware stuff. +// Other types expand it - tablets use a direct subtypes, and +// consoles and laptops use "procssor" item that is held inside machinery piece +/obj/item/device/modular_computer + name = "modular microcomputer" + desc = "A small portable microcomputer." + + var/enabled = 0 // Whether the computer is turned on. + var/screen_on = 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 + var/last_battery_percent = 0 // Used for deciding if battery percentage has chandged + var/last_world_time = "00:00" + var/list/last_header_icons + var/emagged = 0 // Whether the computer is emagged. + + 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) + + // 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. + + icon = 'icons/obj/computer.dmi' + icon_state = "laptop-open" + var/icon_state_unpowered = null // Icon state when the computer is turned off. + var/icon_state_powered = null // Icon state when the computer is turned on. + 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 w_class. Tablets/PDAs have 1, laptops 2, consoles 4. + var/steel_sheet_cost = 5 // Amount of steel sheets refunded when disassembling an empty frame of this computer. + + // 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. + var/obj/item/weapon/computer_hardware/hard_drive/hard_drive // Hard Drive component of this computer. Stores programs and files. + + var/obj/item/weapon/computer_hardware/battery/battery_module // Power cell connector. Power cell can be recharged. + // OR + var/obj/item/weapon/computer_hardware/recharger/recharger // Recharger. Can be used to recharge power cell or power the PC without it. + + // Optional hardware (improves functionality, but is not critical for computer to work) + var/obj/item/weapon/computer_hardware/network_card/network_card // Network Card component of this computer. Allows connection to NTNet. + var/obj/item/weapon/computer_hardware/card_slot/card_slot // ID Card slot component of this computer. + var/obj/item/weapon/computer_hardware/printer/printer // Printer component of this computer, for your everyday paperwork needs. + var/obj/item/weapon/computer_hardware/hard_drive/portable/portable_drive // Portable data storage + + var/list/all_components = list() + + var/list/idle_threads = list() // Idle programs on background. They still receive process calls but can't be interacted with. + var/obj/physical = null // Object that represents our computer. It's used for Adjacent() and UI visibility checks. + + + +/obj/item/device/modular_computer/New() + START_PROCESSING(SSobj, src) + update_icon() + if(!physical) + physical = src + ..() + +/obj/item/device/modular_computer/Destroy() + kill_program(forced = TRUE) + STOP_PROCESSING(SSobj, src) + for(var/H in all_components) + qdel(H) + return ..() + +// Eject ID card from computer, if it has ID slot with card inside. +/obj/item/device/modular_computer/verb/eject_id() + set name = "Eject ID" + set category = "Object" + set src in view(1) + + if(issilicon(usr)) + return + + if (usr.canUseTopic(src)) + proc_eject_id(usr) + +// Eject ID card from computer, if it has ID slot with card inside. +/obj/item/device/modular_computer/verb/eject_disk() + set name = "Eject Data Disk" + set category = "Object" + set src in view(1) + + if(issilicon(usr)) + return + + if (usr.canUseTopic(src)) + proc_eject_disk(usr) + +/obj/item/device/modular_computer/proc/proc_eject_id(mob/user, slot) + if(!user) + user = usr + + if(!card_slot) + user << "\The [src] does not have an ID card slot!" + return + + card_slot.try_eject(slot, user) + +/obj/item/device/modular_computer/proc/proc_eject_disk(mob/user) + if(!user) + user = usr + + if(!portable_drive) + user << "There is no data disk in \the [src]!" + return + + var/obj/item/I = portable_drive + if(uninstall_component(portable_drive, user)) + I.verb_pickup() + +/obj/item/device/modular_computer/AltClick(mob/user) + ..() + if(issilicon(user)) + return + + if(user.canUseTopic(src)) + if(portable_drive) + proc_eject_disk(user) + else if(card_slot) + proc_eject_id(user) + + +// Gets IDs/access levels from card slot. Would be useful when/if PDAs would become modular PCs. +/obj/item/device/modular_computer/GetAccess() + if(card_slot) + return card_slot.GetAccess() + return ..() + +/obj/item/device/modular_computer/GetID() + if(card_slot) + return card_slot.GetID() + return ..() + +/obj/item/device/modular_computer/MouseDrop(obj/over_object, src_location, over_location) + var/mob/M = usr + if((!istype(over_object, /obj/screen)) && usr.canUseTopic(src)) + return attack_self(M) + return + +/obj/item/device/modular_computer/attack_ghost(mob/dead/observer/user) + if(enabled) + ui_interact(user) + else if(IsAdminGhost(user)) + var/response = alert(user, "This computer is turned off. Would you like to turn it on?", "Admin Override", "Yes", "No") + if(response == "Yes") + turn_on(user) + +/obj/item/device/modular_computer/emag_act(mob/user) + if(emagged) + user << "\The [src] was already emagged." + return 0 + else + emagged = 1 + user << "You emag \the [src]. It's screen briefly shows a \"OVERRIDE ACCEPTED: New software downloads available.\" message." + return 1 + +/obj/item/device/modular_computer/examine(mob/user) + ..() + if(damage > broken_damage) + user << "It is heavily damaged!" + else if(damage) + user << "It is damaged." + +/obj/item/device/modular_computer/update_icon() + cut_overlays() + if(!enabled) + icon_state = icon_state_unpowered + else + icon_state = icon_state_powered + if(active_program) + add_overlay(active_program.program_icon_state ? active_program.program_icon_state : icon_state_menu) + else + add_overlay(icon_state_menu) + + if(damage > broken_damage) + add_overlay("bsod") + add_overlay("broken") + + +// On-click handling. Turns on the computer if it's off and opens the GUI. +/obj/item/device/modular_computer/attack_self(mob/user) + if(enabled) + ui_interact(user) + else + turn_on(user) + +/obj/item/device/modular_computer/proc/turn_on(mob/user) + var/issynth = issilicon(user) // Robots and AIs get different activation messages. + 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 we have a recharger, enable it automatically. Lets computer without a battery work. + if(recharger) + recharger.enabled = 1 + + if(processor_unit && use_power()) // use_power() checks if the PC is powered + if(issynth) + user << "You send an activation signal to \the [src], turning it on." + else + user << "You press the power button and start up \the [src]." + enabled = 1 + update_icon() + ui_interact(user) + else // Unpowered + if(issynth) + user << "You send an activation signal to \the [src] but it does not respond." + else + user << "You press the power button but \the [src] does not respond." + +// Process currently calls handle_power(), may be expanded in future if more things are added. +/obj/item/device/modular_computer/process() + if(!enabled) // The computer is turned off + 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.event_networkfailure(0) // Active program requires NTNet to run but we've just lost connection. Crash. + + for(var/I in idle_threads) + var/datum/computer_file/program/P = I + if(P.requires_ntnet && !get_ntnet_status(P.requires_ntnet_feature)) + P.event_networkfailure(1) + + if(active_program) + if(active_program.program_state != PROGRAM_STATE_KILLED) + active_program.process_tick() + active_program.ntnet_status = get_ntnet_status() + else + active_program = null + + for(var/I in idle_threads) + var/datum/computer_file/program/P = I + if(P.program_state != PROGRAM_STATE_KILLED) + P.process_tick() + P.ntnet_status = get_ntnet_status() + else + idle_threads.Remove(P) + + handle_power() // Handles all computer power interaction + //check_update_ui_need() + +// Function used by NanoUI's to obtain data for header. All relevant entries begin with "PC_" +/obj/item/device/modular_computer/proc/get_header_data() + var/list/data = list() + + if(battery_module && battery_module.battery) + switch(battery_module.battery.percent()) + if(80 to 200) // 100 should be maximal but just in case.. + data["PC_batteryicon"] = "batt_100.gif" + if(60 to 80) + data["PC_batteryicon"] = "batt_80.gif" + if(40 to 60) + data["PC_batteryicon"] = "batt_60.gif" + if(20 to 40) + data["PC_batteryicon"] = "batt_40.gif" + if(5 to 20) + data["PC_batteryicon"] = "batt_20.gif" + else + data["PC_batteryicon"] = "batt_5.gif" + data["PC_batterypercent"] = "[round(battery_module.battery.percent())] %" + data["PC_showbatteryicon"] = 1 + else + data["PC_batteryicon"] = "batt_5.gif" + data["PC_batterypercent"] = "N/C" + data["PC_showbatteryicon"] = battery_module ? 1 : 0 + + if(recharger && recharger.enabled && recharger.check_functionality() && recharger.use_power(0)) + data["PC_apclinkicon"] = "charging.gif" + + switch(get_ntnet_status()) + if(0) + data["PC_ntneticon"] = "sig_none.gif" + if(1) + data["PC_ntneticon"] = "sig_low.gif" + if(2) + data["PC_ntneticon"] = "sig_high.gif" + if(3) + data["PC_ntneticon"] = "sig_lan.gif" + + if(idle_threads.len) + var/list/program_headers = list() + for(var/I in idle_threads) + var/datum/computer_file/program/P = I + if(!P.ui_header) + continue + program_headers.Add(list(list( + "icon" = P.ui_header + ))) + + data["PC_programheaders"] = program_headers + + data["PC_stationtime"] = worldtime2text() + data["PC_hasheader"] = 1 + data["PC_showexitprogram"] = active_program ? 1 : 0 // Hides "Exit Program" button on mainscreen + return data + +// Relays kill program request to currently active program. Use this to quit current program. +/obj/item/device/modular_computer/proc/kill_program(forced = FALSE) + if(active_program) + active_program.kill_program(forced) + active_program = null + var/mob/user = usr + if(user && istype(user)) + ui_interact(user) // Re-open the UI on this computer. It should show the main screen now. + update_icon() + +// Returns 0 for No Signal, 1 for Low Signal and 2 for Good Signal. 3 is for wired connection (always-on) +/obj/item/device/modular_computer/proc/get_ntnet_status(specific_action = 0) + if(network_card) + return network_card.get_signal(specific_action) + else + return 0 + +/obj/item/device/modular_computer/proc/add_log(text) + if(!get_ntnet_status()) + return FALSE + return ntnet_global.add_log(text, network_card) + +/obj/item/device/modular_computer/proc/shutdown_computer(loud = 1) + kill_program(forced = TRUE) + for(var/datum/computer_file/program/P in idle_threads) + P.kill_program(forced = TRUE) + idle_threads.Remove(P) + if(loud) + physical.visible_message("\The [src] shuts down.") + enabled = 0 + update_icon() + + +/obj/item/device/modular_computer/attackby(obj/item/weapon/W as obj, mob/user as mob) + // Insert items into the components + for(var/h in all_components) + var/obj/item/weapon/computer_hardware/H = h + if(H.try_insert(W, user)) + return + + // Insert new hardware + if(istype(W, /obj/item/weapon/computer_hardware)) + if(install_component(W, user)) + return + + if(istype(W, /obj/item/weapon/wrench)) + if(all_components.len) + user << "Remove all components from \the [src] before disassembling it." + return + new /obj/item/stack/sheet/metal( get_turf(src.loc), steel_sheet_cost ) + physical.visible_message("\The [src] has been disassembled by [user].") + 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(istype(W, /obj/item/weapon/screwdriver)) + if(!all_components.len) + user << "This device doesn't have any components installed." + return + var/list/component_names = list() + for(var/obj/item/weapon/computer_hardware/H in all_components) + component_names.Add(H.name) + + var/choice = input(usr, "Which component do you want to uninstall?", "Computer maintenance", null) as null|anything in component_names + + if(!choice) + return + + if(!Adjacent(usr)) + return + + var/obj/item/weapon/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. +/obj/item/device/modular_computer/proc/relay_qdel() + return + +// Perform adjacency checks on our physical counterpart, if any. +/obj/item/device/modular_computer/Adjacent(atom/neighbor) + if(physical && physical != src) + return physical.Adjacent(neighbor) + return ..() diff --git a/code/modules/modular_computers/computers/item/computer_components.dm b/code/modules/modular_computers/computers/item/computer_components.dm new file mode 100644 index 00000000000..3a5b68579e1 --- /dev/null +++ b/code/modules/modular_computers/computers/item/computer_components.dm @@ -0,0 +1,117 @@ +/obj/item/device/modular_computer/proc/can_install_component(obj/item/weapon/computer_hardware/H, mob/living/user = null) + if(!H.can_install(src, user)) + return FALSE + + if(H.w_class > max_hardware_size) + user << "This component is too large for \the [src]!" + return FALSE + + if(istype(H, /obj/item/weapon/computer_hardware/hard_drive/portable) && portable_drive) + user << "This computer's FDD is already occupied by \the [portable_drive]." + return FALSE + + else if(istype(H, /obj/item/weapon/computer_hardware/processor_unit) && processor_unit) + user << "This computer's CPU slot is already occupied by \the [processor_unit]." + return FALSE + else if(istype(H, /obj/item/weapon/computer_hardware/hard_drive) && hard_drive) + user << "This computer's data port is already occupied by \the [hard_drive]." + return FALSE + + else if(istype(H, /obj/item/weapon/computer_hardware/battery) && battery_module) + user << "This computer's power converter slot is already occupied by \the [battery_module]." + return FALSE + else if(istype(H, /obj/item/weapon/computer_hardware/recharger) && recharger) + user << "This computer's recharger slot is already occupied by \the [recharger]." + return FALSE + + else if(istype(H, /obj/item/weapon/computer_hardware/card_slot) && card_slot) + user << "This computer's card reader slot is already occupied by \the [card_slot]." + return FALSE + else if(istype(H, /obj/item/weapon/computer_hardware/network_card) && network_card) + user << "This computer's network card is already occupied by \the [network_card]." + return FALSE + else if(istype(H, /obj/item/weapon/computer_hardware/printer) && printer) + user << "This computer's printer slot is already occupied by \the [printer]." + return FALSE + return TRUE + + +// Installs component. +/obj/item/device/modular_computer/proc/install_component(obj/item/weapon/computer_hardware/H, mob/living/user = null) + if(!can_install_component(H, user)) + return FALSE + + if(user && !user.unEquip(H)) + return FALSE + + if(istype(H, /obj/item/weapon/computer_hardware/hard_drive/portable)) + portable_drive = H + + else if(istype(H, /obj/item/weapon/computer_hardware/processor_unit)) + processor_unit = H + else if(istype(H, /obj/item/weapon/computer_hardware/hard_drive)) + hard_drive = H + + else if(istype(H, /obj/item/weapon/computer_hardware/battery)) + battery_module = H + else if(istype(H, /obj/item/weapon/computer_hardware/recharger)) + recharger = H + + else if(istype(H, /obj/item/weapon/computer_hardware/card_slot)) + card_slot = H + else if(istype(H, /obj/item/weapon/computer_hardware/network_card)) + network_card = H + else if(istype(H, /obj/item/weapon/computer_hardware/printer)) + printer = H + + user << "You install \the [H] into \the [src]." + H.forceMove(src) + H.holder = src + all_components |= H + H.on_install(src, user) + return TRUE + + +// Uninstalls component. +/obj/item/device/modular_computer/proc/uninstall_component(obj/item/weapon/computer_hardware/H, mob/living/user = null) + if(H.holder != src) // Not our component at all. + return FALSE + + if(processor_unit == H) + processor_unit = null + if(hard_drive == H) + hard_drive = null + + if(battery_module == H) + battery_module = null + if(recharger == H) + recharger = null + + if(card_slot == H) + card_slot = null + if(network_card == H) + network_card = null + if(printer == H) + printer = null + if(portable_drive == H) + portable_drive = null + + user << "You remove \the [H] from \the [src]." + + H.forceMove(get_turf(src)) + H.holder = null + all_components -= H + H.on_remove(src, user) + if(enabled && (!processor_unit || !hard_drive || !use_power())) + shutdown_computer() + update_icon() + return TRUE + + +// Checks all hardware pieces to determine if name matches, if yes, returns the hardware piece, otherwise returns null +/obj/item/device/modular_computer/proc/find_hardware_by_name(name) + for(var/i in all_components) + var/obj/O = i + if(O.name == name) + return O + return null diff --git a/code/modules/modular_computers/computers/item/computer_damage.dm b/code/modules/modular_computers/computers/item/computer_damage.dm new file mode 100644 index 00000000000..8214840bc2b --- /dev/null +++ b/code/modules/modular_computers/computers/item/computer_damage.dm @@ -0,0 +1,49 @@ +/obj/item/device/modular_computer/proc/take_damage(amount, component_probability, damage_casing = 1, 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 = max(0,min(max_damage,damage)) + + if(component_probability) + for(var/I in all_components) + var/obj/item/weapon/computer_hardware/H = I + 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/device/modular_computer/ex_act(severity) + take_damage(rand(100,200)/severity, component_probability = 30/severity) + +// EMPs are similar to explosions, but don't cause physical damage to the casing. Instead they screw up the components +/obj/item/device/modular_computer/emp_act(severity) + take_damage(rand(100,200)/severity, component_probability = 50/severity, damage_casing = 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/device/modular_computer/bullet_act(obj/item/projectile/Proj) + switch(Proj.damage_type) + if(BRUTE) + take_damage(Proj.damage, component_probability = Proj.damage/2) + if(BURN) + take_damage(Proj.damage, component_probability = Proj.damage/1.5) + +/obj/item/device/modular_computer/proc/break_apart() + physical.visible_message("\The [src] breaks apart!") + var/turf/newloc = get_turf(src) + new /obj/item/stack/sheet/metal(newloc, round(steel_sheet_cost/2)) + for(var/C in all_components) + var/obj/item/weapon/computer_hardware/H = C + uninstall_component(H) + H.forceMove(newloc) + if(prob(25)) + H.take_damage(rand(10,30)) + relay_qdel() + qdel() diff --git a/code/modules/modular_computers/computers/item/computer_power.dm b/code/modules/modular_computers/computers/item/computer_power.dm new file mode 100644 index 00000000000..f6196477000 --- /dev/null +++ b/code/modules/modular_computers/computers/item/computer_power.dm @@ -0,0 +1,55 @@ +// Tries to draw power from charger or, if no operational charger is present, from power cell. +/obj/item/device/modular_computer/proc/use_power(amount = 0) + if(check_power_override()) + return TRUE + + if(recharger && recharger.check_functionality()) + if(recharger.use_power(amount)) + return TRUE + + if(battery_module && battery_module.battery && battery_module.battery.charge) + var/obj/item/weapon/stock_parts/cell/cell = battery_module.battery + if(cell.use(amount * CELLRATE)) + return TRUE + else // Discharge the cell anyway. + cell.use(min(amount*CELLRATE, cell.charge)) + return FALSE + return FALSE + +/obj/item/device/modular_computer/proc/give_power(amount) + if(battery_module && battery_module.battery) + return battery_module.battery.give(amount) + return 0 + + +// Used in following function to reduce copypaste +/obj/item/device/modular_computer/proc/power_failure() + if(enabled) // Shut down the computer + if(active_program) + active_program.event_powerfailure(0) + for(var/I in idle_threads) + var/datum/computer_file/program/PRG = I + PRG.event_powerfailure(1) + shutdown_computer(0) + +// Handles power-related things, such as battery interaction, recharging, shutdown when it's discharged +/obj/item/device/modular_computer/proc/handle_power() + if(recharger) + recharger.process() + + var/power_usage = screen_on ? base_active_power_usage : base_idle_power_usage + + for(var/obj/item/weapon/computer_hardware/H in all_components) + if(H.enabled) + power_usage += H.power_usage + + if(use_power(power_usage)) + last_power_usage = power_usage + return TRUE + else + power_failure() + return FALSE + +// Used by child types if they have other power source than battery or recharger +/obj/item/device/modular_computer/proc/check_power_override() + return FALSE diff --git a/code/modules/modular_computers/computers/item/computer_ui.dm b/code/modules/modular_computers/computers/item/computer_ui.dm new file mode 100644 index 00000000000..a89e84b31f4 --- /dev/null +++ b/code/modules/modular_computers/computers/item/computer_ui.dm @@ -0,0 +1,132 @@ +// Operates TGUI +/obj/item/device/modular_computer/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = default_state) + if(!enabled) + if(ui) + ui.close() + return 0 + if(!use_power()) + if(ui) + ui.close() + return 0 + + // 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 + + // If we have an active program switch to it now. + if(active_program) + if(ui) // This is the main laptop screen. Since we are switching to program's UI close it for now. + ui.close() + active_program.ui_interact(user) + return + + // We are still here, that means there is no program loaded. Load the BIOS/ROM/OS/whatever you want to call it. + // This screen simply lists available programs and user may select them. + if(!hard_drive || !hard_drive.stored_files || !hard_drive.stored_files.len) + physical.visible_message("\The [src] beeps three times, it's screen displaying \"DISK ERROR\" warning.") + return // No HDD, No HDD files list or no stored files. Something is very broken. + + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) + if (!ui) + var/datum/asset/assets = get_asset_datum(/datum/asset/simple/headers) + assets.send(user) + + ui = new(user, src, ui_key, "computer_main", "NTOS Main menu", 400, 500, master_ui, state) + ui.open() + ui.set_autoupdate(state = 1) + + +/obj/item/device/modular_computer/ui_data(mob/user) + var/list/data = get_header_data() + data["programs"] = list() + for(var/datum/computer_file/program/P in hard_drive.stored_files) + var/running = 0 + if(P in idle_threads) + running = 1 + + data["programs"] += list(list("name" = P.filename, "desc" = P.filedesc, "running" = running)) + + return data + + +// Handles user's GUI input +/obj/item/device/modular_computer/ui_act(action, params) + if(..()) + return + switch(action) + if("PC_exit") + kill_program() + return 1 + if("PC_shutdown") + shutdown_computer() + return 1 + if("PC_minimize") + var/mob/user = usr + if(!active_program || !processor_unit) + return + + idle_threads.Add(active_program) + active_program.program_state = PROGRAM_STATE_BACKGROUND // Should close any existing UIs + + active_program = null + update_icon() + if(user && istype(user)) + ui_interact(user) // Re-open the UI on this computer. It should show the main screen now. + + if("PC_killprogram") + var/prog = params["name"] + var/datum/computer_file/program/P = null + var/mob/user = usr + if(hard_drive) + P = hard_drive.find_file_by_name(prog) + + if(!istype(P) || P.program_state == PROGRAM_STATE_KILLED) + return + + P.kill_program(forced = TRUE) + user << "Program [P.filename].[P.filetype] with PID [rand(100,999)] has been killed." + + if("PC_runprogram") + var/prog = params["name"] + var/datum/computer_file/program/P = null + var/mob/user = usr + if(hard_drive) + P = hard_drive.find_file_by_name(prog) + + 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 + + // The program is already running. Resume it. + if(P in idle_threads) + P.program_state = PROGRAM_STATE_ACTIVE + active_program = P + idle_threads.Remove(P) + update_icon() + return + + if(idle_threads.len >= processor_unit.max_idle_programs+1) + user << "\The [src] displays a \"Maximal CPU load reached. Unable to run another program.\" error." + return + + if(P.requires_ntnet && !get_ntnet_status(P.requires_ntnet_feature)) // The program requires NTNet connection, but we are not connected to NTNet. + user << "\The [src]'s screen shows \"Unable to connect to NTNet. Please retry. If problem persists contact your system administrator.\" warning." + return + if(P.run_program(user)) + active_program = P + update_icon() + return 1 + else + return + +/obj/item/device/modular_computer/ui_host() + if(physical) + return physical + return src diff --git a/code/modules/modular_computers/computers/item/laptop.dm b/code/modules/modular_computers/computers/item/laptop.dm new file mode 100644 index 00000000000..51c91a595ae --- /dev/null +++ b/code/modules/modular_computers/computers/item/laptop.dm @@ -0,0 +1,106 @@ +/obj/item/device/modular_computer/laptop + name = "laptop" + desc = "A portable laptop computer." + + icon = 'icons/obj/modular_laptop.dmi' + icon_state = "laptop-closed" + icon_state_powered = "laptop" + icon_state_unpowered = "laptop-off" + icon_state_menu = "menu" + + hardware_flag = PROGRAM_LAPTOP + max_hardware_size = 2 + w_class = 3 + + flags = HANDSLOW // No running around with open laptops in hands. + + screen_on = 0 // Starts closed + var/start_open = 1 // unless this var is set to 1 + var/icon_state_closed = "laptop-closed" + var/w_class_open = 4 + var/slowdown_open = 1 + +/obj/item/device/modular_computer/laptop/New() + ..() + if(start_open && !screen_on) + toggle_open() + +/obj/item/device/modular_computer/laptop/update_icon() + if(screen_on) + ..() + else + cut_overlays() + icon_state = icon_state_closed + +/obj/item/device/modular_computer/laptop/attack_self(mob/user) + if(!screen_on) + try_toggle_open(user) + else + return ..() + +/obj/item/device/modular_computer/laptop/verb/open_computer() + set name = "Toggle Open" + set category = "Object" + set src in view(1) + + try_toggle_open(usr) + +/obj/item/device/modular_computer/laptop/MouseDrop(obj/over_object, src_location, over_location) + if(over_object == usr || over_object == src) + try_toggle_open(usr) + else 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 + + switch(H.slot_id) + if(slot_r_hand) + M.put_in_r_hand(src) + if(slot_l_hand) + M.put_in_l_hand(src) + +/obj/item/device/modular_computer/laptop/attack_hand(mob/user) + if(screen_on && isturf(loc)) + return attack_self(user) + + return ..() + + +/obj/item/device/modular_computer/laptop/proc/try_toggle_open(mob/living/user) + if(issilicon(user)) + return + if(!isturf(loc) && !ismob(loc)) // No opening it in backpack. + return + if(!user.canUseTopic(src)) + return + + toggle_open(user) + + +/obj/item/device/modular_computer/laptop/AltClick(mob/user) + if(screen_on) // Close it. + try_toggle_open(user) + else + return ..() + +/obj/item/device/modular_computer/laptop/proc/toggle_open(mob/living/user=null) + if(screen_on) + user << "You close \the [src]." + slowdown = initial(slowdown) + w_class = initial(w_class) + else + user << "You open \the [src]." + slowdown = slowdown_open + w_class = w_class_open + + screen_on = !screen_on + update_icon() + + + +// Laptop frame, starts empty and closed. +/obj/item/device/modular_computer/laptop/buildable + start_open = 0 diff --git a/code/modules/modular_computers/computers/item/modular_computer.dm b/code/modules/modular_computers/computers/item/modular_computer.dm deleted file mode 100644 index 6314cb69913..00000000000 --- a/code/modules/modular_computers/computers/item/modular_computer.dm +++ /dev/null @@ -1,704 +0,0 @@ -// This is the base type that does all the hardware stuff. -// Other types expand it - tablets use a direct subtypes, and -// consoles and laptops use "procssor" item that is held inside machinery piece -/obj/item/modular_computer - name = "Modular Microcomputer" - desc = "A small portable microcomputer." - - var/enabled = 0 // Whether the computer is turned on. - var/screen_on = 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 - var/last_battery_percent = 0 // Used for deciding if battery percentage has chandged - var/last_world_time = "00:00" - var/list/last_header_icons - var/computer_emagged = 0 // Whether the computer is emagged. - - 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) - - // 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. - - icon = 'icons/obj/computer.dmi' - icon_state = "laptop-open" - var/icon_state_unpowered = null // Icon state when the computer is turned off - 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. - - // 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. - var/obj/item/weapon/computer_hardware/network_card/network_card // Network Card component of this computer. Allows connection to NTNet - var/obj/item/weapon/computer_hardware/hard_drive/hard_drive // Hard Drive component of this computer. Stores programs and files. - var/obj/item/weapon/computer_hardware/battery_module/battery_module // An internal power source for this computer. Can be recharged. - // Optional hardware (improves functionality, but is not critical for computer to work) - var/obj/item/weapon/computer_hardware/card_slot/card_slot // ID Card slot component of this computer. Mostly for HoP modification console that needs ID slot for modification. - var/obj/item/weapon/computer_hardware/card_slot/card_slot2 // second slot. popular demand requested the hop need to insert 2 ids. - var/obj/item/weapon/computer_hardware/nano_printer/nano_printer // Nano Printer component of this computer, for your everyday paperwork needs. - var/obj/item/weapon/computer_hardware/hard_drive/portable/portable_drive // Portable data storage - - var/list/idle_threads = list() // Idle programs on background. They still receive process calls but can't be interacted with. - var/obj/physical = null - - - -// Eject ID card from computer, if it has ID slot with card inside. -/obj/item/modular_computer/verb/eject_id() - set name = "Eject ID" - 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_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, slot) - if(!user) - user = usr - - if(!card_slot) - user << "\The [src] does not have an ID card slot" - return - - if(!card_slot.stored_card && !card_slot.stored_card2) - user << "There is no card in \the [src]" - return - - if(active_program) - active_program.event_idremoved(0, slot) - - for(var/I in idle_threads) - var/datum/computer_file/program/P = I - P.event_idremoved(1, slot) - if(card_slot.stored_card && (!slot || slot == 1)) - card_slot.stored_card.forceMove(get_turf(src)) - card_slot.stored_card = null - if(card_slot.stored_card2 && (!slot || slot == 2)) - card_slot.stored_card2.forceMove(get_turf(src)) - card_slot.stored_card2 = null - user << "You remove the card[card_slot.stored_card && card_slot.stored_card2 && !slot ? "s" : ""] 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) - -/obj/item/modular_computer/attack_ghost(mob/dead/observer/user) - if(enabled) - ui_interact(user) - else if(IsAdminGhost(user)) - var/response = alert(user, "This computer is turned off. Would you like to turn it on?", "Admin Override", "Yes", "No") - if(response == "Yes") - turn_on(user) - -/obj/item/modular_computer/emag_act(mob/user) - if(computer_emagged) - user << "\The [src] was already emagged." - return 0 - else - computer_emagged = 1 - 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(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(SSmachine, src) - update_icon() - if(!physical) - physical = src - ..() - -/obj/item/modular_computer/Destroy() - kill_program(1) - STOP_PROCESSING(SSmachine, src) - for(var/H in get_all_components()) - var/obj/item/weapon/computer_hardware/CH = H - uninstall_component(null, CH) - qdel(CH) - return ..() - -/obj/item/modular_computer/update_icon() - icon_state = icon_state_unpowered - cut_overlays() - if(!enabled) - return - if(active_program) - add_overlay(active_program.program_icon_state ? active_program.program_icon_state : icon_state_menu) - else - add_overlay(icon_state_menu) - -// Used by child types if they have other power source than battery -/obj/item/modular_computer/proc/check_power_override() - return 0 - -// Operates NanoUI -/obj/item/modular_computer/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = default_state) - - - if(!screen_on || !enabled) - if(ui) - ui.close() - return 0 - if((!battery_module || !battery_module.battery.charge) && !check_power_override()) - if(ui) - ui.close() - return 0 - - // If we have an active program switch to it now. - if(active_program) - if(ui) // This is the main laptop screen. Since we are switching to program's UI close it for now. - ui.close() - active_program.ui_interact(user) - return - - // We are still here, that means there is no program loaded. Load the BIOS/ROM/OS/whatever you want to call it. - // This screen simply lists available programs and user may select them. - if(!hard_drive || !hard_drive.stored_files || !hard_drive.stored_files.len) - physical.visible_message("\The [src] beeps three times, it's screen displaying \"DISK ERROR\" warning.") - return // No HDD, No HDD files list or no stored files. Something is very broken. - - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) - if (!ui) - - var/datum/asset/assets = get_asset_datum(/datum/asset/simple/headers) - assets.send(user) - - ui = new(user, src, ui_key, "computer_main", "NTOS Main menu", 400, 500, master_ui, state) - ui.open() - ui.set_autoupdate(state = 1) - - -/obj/item/modular_computer/ui_data(mob/user) - - var/list/data = get_header_data() - data["programs"] = list() - for(var/datum/computer_file/program/P in hard_drive.stored_files) - var/running = 0 - if(P in idle_threads) - running = 1 - - data["programs"] += list(list("name" = P.filename, "desc" = P.filedesc, "running" = running)) - - return data - - -// On-click handling. Turns on the computer if it's off and opens the GUI. -/obj/item/modular_computer/attack_self(mob/user) - if(enabled) - ui_interact(user) - else - turn_on(user) - -/obj/item/modular_computer/proc/break_apart() - physical.visible_message("\The [src] breaks apart!") - var/turf/newloc = get_turf(src) - new /obj/item/stack/sheet/metal(newloc, round(steel_sheet_cost/2)) - for(var/C in get_all_components()) - var/obj/item/weapon/computer_hardware/H = C - 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(mob/user) - var/issynth = issilicon(user) // Robots and AIs get different activation messages. - 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 - user << "You press the power button and start up \the [src]" - enabled = 1 - update_icon() - ui_interact(user) - else // Unpowered - if(issynth) - user << "You send an activation signal to \the [src] but it does not respond" - else - user << "You press the power button but \the [src] does not respond" - -// 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(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) - - for(var/I in idle_threads) - var/datum/computer_file/program/P = I - if(P.requires_ntnet && !get_ntnet_status(P.requires_ntnet_feature)) - P.event_networkfailure(1) - - if(active_program) - if(active_program.program_state != PROGRAM_STATE_KILLED) - active_program.process_tick() - active_program.ntnet_status = get_ntnet_status() - active_program.computer_emagged = computer_emagged - else - active_program = null - - for(var/I in idle_threads) - var/datum/computer_file/program/P = I - if(P.program_state != PROGRAM_STATE_KILLED) - P.process_tick() - P.ntnet_status = get_ntnet_status() - P.computer_emagged = computer_emagged - else - idle_threads.Remove(P) - - handle_power() // Handles all computer power interaction - //check_update_ui_need() - -// 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() - - if(battery_module) - switch(battery_module.battery.percent()) - if(80 to 200) // 100 should be maximal but just in case.. - data["PC_batteryicon"] = "batt_100.gif" - if(60 to 80) - data["PC_batteryicon"] = "batt_80.gif" - if(40 to 60) - data["PC_batteryicon"] = "batt_60.gif" - if(20 to 40) - data["PC_batteryicon"] = "batt_40.gif" - if(5 to 20) - data["PC_batteryicon"] = "batt_20.gif" - else - data["PC_batteryicon"] = "batt_5.gif" - data["PC_batterypercent"] = "[round(battery_module.battery.percent())] %" - data["PC_showbatteryicon"] = 1 - else - data["PC_batteryicon"] = "batt_5.gif" - data["PC_batterypercent"] = "N/C" - data["PC_showbatteryicon"] = battery_module ? 1 : 0 - - switch(get_ntnet_status()) - if(0) - data["PC_ntneticon"] = "sig_none.gif" - if(1) - data["PC_ntneticon"] = "sig_low.gif" - if(2) - data["PC_ntneticon"] = "sig_high.gif" - if(3) - data["PC_ntneticon"] = "sig_lan.gif" - - if(idle_threads.len) - var/list/program_headers = list() - for(var/I in idle_threads) - var/datum/computer_file/program/P = I - if(!P.ui_header) - continue - program_headers.Add(list(list( - "icon" = P.ui_header - ))) - - data["PC_programheaders"] = program_headers - - data["PC_stationtime"] = worldtime2text() - data["PC_hasheader"] = 1 - data["PC_showexitprogram"] = active_program ? 1 : 0 // Hides "Exit Program" button on mainscreen - return data - -// Relays kill program request to currently active program. Use this to quit current program. -/obj/item/modular_computer/proc/kill_program(forced = 0) - if(active_program) - active_program.kill_program(forced) - active_program = null - var/mob/user = usr - if(user && istype(user)) - ui_interact(user) // Re-open the UI on this computer. It should show the main screen now. - update_icon() - -// Returns 0 for No Signal, 1 for Low Signal and 2 for Good Signal. 3 is for wired connection (always-on) -/obj/item/modular_computer/proc/get_ntnet_status(specific_action = 0) - if(network_card) - return network_card.get_signal(specific_action) - else - return 0 - -/obj/item/modular_computer/proc/add_log(text) - if(!get_ntnet_status()) - return 0 - return ntnet_global.add_log(text, network_card) - -/obj/item/modular_computer/proc/shutdown_computer(loud = 1) - kill_program(1) - for(var/datum/computer_file/program/P in idle_threads) - P.kill_program(1) - idle_threads.Remove(P) - if(loud) - physical.visible_message("\The [src] shuts down.") - enabled = 0 - update_icon() - return - -// Handles user's GUI input -/obj/item/modular_computer/ui_act(action, params) - if(..()) - return - switch(action) - if("PC_exit") - kill_program() - return 1 - if("PC_shutdown") - shutdown_computer() - return 1 - if("PC_minimize") - var/mob/user = usr - if(!active_program || !processor_unit) - return - - idle_threads.Add(active_program) - active_program.program_state = PROGRAM_STATE_BACKGROUND // Should close any existing UIs - - active_program = null - update_icon() - if(user && istype(user)) - ui_interact(user) // Re-open the UI on this computer. It should show the main screen now. - - if("PC_killprogram") - var/prog = params["name"] - var/datum/computer_file/program/P = null - var/mob/user = usr - if(hard_drive) - P = hard_drive.find_file_by_name(prog) - - if(!istype(P) || P.program_state == PROGRAM_STATE_KILLED) - return - - P.kill_program(1) - user << "Program [P.filename].[P.filetype] with PID [rand(100,999)] has been killed." - - if("PC_runprogram") - var/prog = params["name"] - var/datum/computer_file/program/P = null - var/mob/user = usr - if(hard_drive) - P = hard_drive.find_file_by_name(prog) - - 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 - - // The program is already running. Resume it. - if(P in idle_threads) - P.program_state = PROGRAM_STATE_ACTIVE - active_program = P - idle_threads.Remove(P) - update_icon() - return - - if(idle_threads.len >= processor_unit.max_idle_programs+1) - user << "\The [src] displays a \"Maximal CPU load reached. Unable to run another program.\" error" - return - - if(P.requires_ntnet && !get_ntnet_status(P.requires_ntnet_feature)) // The program requires NTNet connection, but we are not connected to NTNet. - user << "\The [src]'s screen shows \"NETWORK ERROR - Unable to connect to NTNet. Please retry. If problem persists contact your system administrator.\" warning." - return - P.computer_emagged = computer_emagged - if(P.run_program(user)) - active_program = P - update_icon() - return 1 - else - return - -// Used in following function to reduce copypaste -/obj/item/modular_computer/proc/power_failure(malfunction = 0) - if(enabled) // Shut down the computer - physical.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/I in idle_threads) - var/datum/computer_file/program/PRG = I - PRG.event_powerfailure(1) - shutdown_computer(0) - -// Handles power-related things, such as battery interaction, recharging, shutdown when it's discharged -/obj/item/modular_computer/proc/handle_power() - if(!battery_module || battery_module.battery.charge <= 0) // Battery-run but battery is depleted. - power_failure() - return 0 - - var/power_usage = screen_on ? base_active_power_usage : base_idle_power_usage - - for(var/obj/item/weapon/computer_hardware/H in get_all_components()) - if(H.enabled) - power_usage += H.power_usage - - if(battery_module) - if(!battery_module.check_functionality()) - power_failure(1) - return - if(!battery_module.battery.use(power_usage * CELLRATE)) - battery_module.battery.charge = 0 - power_failure() - return 0 - - last_power_usage = power_usage - -/obj/item/modular_computer/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(istype(W, /obj/item/weapon/card/id)) // ID Card, try to insert it. - var/obj/item/weapon/card/id/I = W - if(!card_slot) - user << "You try to insert \the [I] into \the [src], but it does not have an ID card slot installed." - return - - if(card_slot.stored_card && card_slot.stored_card2) - user << "You try to insert \the [I] into \the [src], but it's ID card slots are occupied." - return - if(!user.drop_item(I)) - return - if(!card_slot.stored_card) - card_slot.stored_card = I - else - card_slot.stored_card2 = I - I.forceMove(src) -// update_uis() - user << "You insert \the [I] into \the [src]." - return - if(istype(W, /obj/item/weapon/paper)) - if(!nano_printer) - return - 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) - C.try_install_component(user, src) - else - user << "This component is too large for \the [src]." - if(istype(W, /obj/item/weapon/wrench)) - var/list/components = get_all_components() - if(components.len) - user << "Remove all components from \the [src] before disassembling it." - return - new /obj/item/stack/sheet/metal( get_turf(src.loc), steel_sheet_cost ) - physical.visible_message("\The [src] has been disassembled by [user].") - 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(istype(W, /obj/item/weapon/screwdriver)) - var/list/all_components = get_all_components() - if(!all_components.len) - user << "This device doesn't have any components installed." - return - var/list/component_names = list() - for(var/obj/item/weapon/computer_hardware/H in all_components) - component_names.Add(H.name) - - var/choice = input(usr, "Which component do you want to uninstall?", "Computer maintenance", null) as null|anything in component_names - - if(!choice) - return - - if(!Adjacent(usr)) - return - - var/obj/item/weapon/computer_hardware/H = find_hardware_by_name(choice) - - if(!H) - return - - uninstall_component(user, H) - - return - - ..() - -// Used by processor to relay qdel() to machinery type. -/obj/item/modular_computer/proc/relay_qdel() - return - -// Uninstalls component. Found and Critical vars may be passed by parent types, if they have additional hardware. -/obj/item/modular_computer/proc/uninstall_component(mob/living/user, obj/item/weapon/computer_hardware/H, found = 0, critical = 0) - if(portable_drive == H) - portable_drive = null - found = 1 - if(hard_drive == H) - hard_drive = null - found = 1 - critical = 1 - if(network_card == H) - network_card = null - found = 1 - if(nano_printer == H) - nano_printer = null - found = 1 - if(card_slot == H) - card_slot = null - found = 1 - if(battery_module == H) - battery_module = null - found = 1 - if(processor_unit == H) - processor_unit = null - found = 1 - critical = 1 - if(found) - if(user) - user << "You remove \the [H] from \the [src]." - H.forceMove(get_turf(src)) - H.holder2 = null - if(critical && enabled) - 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() - - -// 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(name) - if(portable_drive && (portable_drive.name == name)) - return portable_drive - 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 - if(battery_module && (battery_module.name == name)) - return battery_module - if(processor_unit && (processor_unit.name == name)) - return processor_unit - return null - -// Returns list of all components -/obj/item/modular_computer/proc/get_all_components() - var/list/all_components = list() - if(hard_drive) - all_components.Add(hard_drive) - if(network_card) - all_components.Add(network_card) - if(portable_drive) - all_components.Add(portable_drive) - if(nano_printer) - all_components.Add(nano_printer) - if(card_slot) - all_components.Add(card_slot) - if(battery_module) - all_components.Add(battery_module) - if(processor_unit) - all_components.Add(processor_unit) - return all_components - -/obj/item/modular_computer/proc/take_damage(amount, component_probability, damage_casing = 1, 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 = max(0,min(max_damage,damage)) - - if(component_probability) - for(var/I in get_all_components()) - var/obj/item/weapon/computer_hardware/H = I - 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(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(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(obj/item/projectile/Proj) - switch(Proj.damage_type) - if(BRUTE) - take_damage(Proj.damage, Proj.damage / 2) - if(BURN) - take_damage(Proj.damage, Proj.damage / 1.5) - -/obj/item/modular_computer/ui_host() - if(physical) - return physical - else - return src \ 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 f9148b66596..65712546ef6 100644 --- a/code/modules/modular_computers/computers/item/processor.dm +++ b/code/modules/modular_computers/computers/item/processor.dm @@ -1,5 +1,5 @@ // Held by /obj/machinery/modular_computer to reduce amount of copy-pasted code. -/obj/item/modular_computer/processor +/obj/item/device/modular_computer/processor name = "processing unit" desc = "You shouldn't see this. If you do, report it." icon = null @@ -10,35 +10,17 @@ var/obj/machinery/modular_computer/machinery_computer = null -/obj/item/modular_computer/processor/Destroy() +/obj/item/device/modular_computer/processor/Destroy() . = ..() if(machinery_computer && (machinery_computer.cpu == src)) machinery_computer.cpu = null machinery_computer = null -// 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 -// non-relayed process calls. -/obj/item/modular_computer/processor/process(relayed = 0) - if(relayed) - ..() - else - return +/obj/item/device/modular_computer/processor/New(comp) + STOP_PROCESSING(SSobj, src) // Processed by its machine -/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) - machinery_computer.handle_power() - -/obj/item/modular_computer/processor/New(comp) if(!comp || !istype(comp, /obj/machinery/modular_computer)) - CRASH("Inapropriate type passed to obj/item/modular_computer/processor/New()! Aborting.") + CRASH("Inapropriate type passed to obj/item/device/modular_computer/processor/New()! Aborting.") return // Obtain reference to machinery computer machinery_computer = comp @@ -48,72 +30,26 @@ steel_sheet_cost = machinery_computer.steel_sheet_cost max_damage = machinery_computer._max_damage broken_damage = machinery_computer._break_damage + base_active_power_usage = machinery_computer.base_active_power_usage + base_idle_power_usage = machinery_computer.base_idle_power_usage -/obj/item/modular_computer/processor/relay_qdel() +/obj/item/device/modular_computer/processor/relay_qdel() qdel(machinery_computer) -/obj/item/modular_computer/processor/find_hardware_by_name(N) - var/obj/item/weapon/computer_hardware/H = machinery_computer.find_hardware_by_name(N) - if(H) - return H - else - return ..() - -/obj/item/modular_computer/processor/update_icon() +/obj/item/device/modular_computer/processor/update_icon() if(machinery_computer) return machinery_computer.update_icon() -/obj/item/modular_computer/processor/get_header_data() - var/list/L = ..() - if(machinery_computer.tesla_link && machinery_computer.tesla_link.enabled && machinery_computer.powered()) - L["PC_apclinkicon"] = "charging.gif" - return L - -// Checks whether the machinery computer doesn't take power from APC network -/obj/item/modular_computer/processor/check_power_override() - if(!machinery_computer) - return 0 - if(!machinery_computer.tesla_link || !machinery_computer.tesla_link.enabled) - return 0 - return machinery_computer.powered() - // 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(user, state) +//obj/item/device/modular_computer/processor/canUseTopic(user, state) // if(!machinery_computer) // return 0 // return machinery_computer.canUseTopic(user, state) -/obj/item/modular_computer/processor/shutdown_computer() +/obj/item/device/modular_computer/processor/shutdown_computer() if(!machinery_computer) return ..() machinery_computer.update_icon() - machinery_computer.use_power = 0 return - -/obj/item/modular_computer/processor/uninstall_component(mob/living/user, obj/item/weapon/computer_hardware/H, found = 0, critical = 0) - if(machinery_computer.tesla_link == H) - machinery_computer.tesla_link = null - var/obj/item/weapon/computer_hardware/tesla_link/L = H - L.holder = null - found = 1 - ..(user, H, found, critical) - -/obj/item/modular_computer/processor/get_all_components() - var/list/all_components = ..() - if(machinery_computer && machinery_computer.tesla_link) - all_components.Add(machinery_computer.tesla_link) - return all_components - -// Perform adjacency checks on our machinery counterpart, rather than on ourselves. -/obj/item/modular_computer/processor/Adjacent(atom/neighbor) - if(!machinery_computer) - return 0 - return machinery_computer.Adjacent(neighbor) - -/obj/item/modular_computer/processor/turn_on(mob/user) - // If we have a tesla link on our machinery counterpart, enable it automatically. Lets computer without a battery work. - if(machinery_computer && machinery_computer.tesla_link) - machinery_computer.tesla_link.enabled = 1 - ..() \ No newline at end of file diff --git a/code/modules/modular_computers/computers/item/tablet.dm b/code/modules/modular_computers/computers/item/tablet.dm index d03c25cca12..0c8cad838de 100644 --- a/code/modules/modular_computers/computers/item/tablet.dm +++ b/code/modules/modular_computers/computers/item/tablet.dm @@ -1,10 +1,11 @@ -/obj/item/modular_computer/tablet +/obj/item/device/modular_computer/tablet name = "tablet computer" icon = 'icons/obj/modular_tablet.dmi' icon_state = "tablet" icon_state_unpowered = "tablet" + icon_state_powered = "tablet" icon_state_menu = "menu" hardware_flag = PROGRAM_TABLET max_hardware_size = 1 w_class = 2 - var/use_power = 0 \ No newline at end of file + steel_sheet_cost = 1 diff --git a/code/modules/modular_computers/computers/item/tablet_presets.dm b/code/modules/modular_computers/computers/item/tablet_presets.dm index ffcb95ce57a..2cc4c700ab5 100644 --- a/code/modules/modular_computers/computers/item/tablet_presets.dm +++ b/code/modules/modular_computers/computers/item/tablet_presets.dm @@ -1,21 +1,21 @@ -// Available as custom loadout item, this is literally the worst possible cheap tablet -/obj/item/modular_computer/tablet/preset/cheap/New() - . = ..() +// This is literally the worst possible cheap tablet +/obj/item/device/modular_computer/tablet/preset/cheap desc = "A low-end tablet often seen among low ranked station personnel." - processor_unit = new/obj/item/weapon/computer_hardware/processor_unit/small(src) - battery_module = new/obj/item/weapon/computer_hardware/battery_module/micro(src) - battery_module.charge_to_full() - hard_drive = new/obj/item/weapon/computer_hardware/hard_drive/micro(src) - network_card = new/obj/item/weapon/computer_hardware/network_card(src) + +/obj/item/device/modular_computer/tablet/preset/cheap/New() + . = ..() + install_component(new /obj/item/weapon/computer_hardware/processor_unit/small) + install_component(new /obj/item/weapon/computer_hardware/battery(src, /obj/item/weapon/stock_parts/cell/computer/micro)) + install_component(new /obj/item/weapon/computer_hardware/hard_drive/small) + install_component(new /obj/item/weapon/computer_hardware/network_card) // Alternative version, an average one, for higher ranked positions mostly -/obj/item/modular_computer/tablet/preset/advanced/New() +/obj/item/device/modular_computer/tablet/preset/advanced/New() . = ..() - processor_unit = new/obj/item/weapon/computer_hardware/processor_unit/small(src) - battery_module = new/obj/item/weapon/computer_hardware/battery_module(src) - battery_module.charge_to_full() - hard_drive = new/obj/item/weapon/computer_hardware/hard_drive/small(src) - network_card = new/obj/item/weapon/computer_hardware/network_card(src) - nano_printer = new/obj/item/weapon/computer_hardware/nano_printer(src) - card_slot = new/obj/item/weapon/computer_hardware/card_slot(src) \ No newline at end of file + install_component(new /obj/item/weapon/computer_hardware/processor_unit/small) + install_component(new /obj/item/weapon/computer_hardware/battery(src, /obj/item/weapon/stock_parts/cell/computer)) + install_component(new /obj/item/weapon/computer_hardware/hard_drive/small) + install_component(new /obj/item/weapon/computer_hardware/network_card) + install_component(new /obj/item/weapon/computer_hardware/card_slot) + install_component(new /obj/item/weapon/computer_hardware/printer/mini) diff --git a/code/modules/modular_computers/computers/machinery/console_presets.dm b/code/modules/modular_computers/computers/machinery/console_presets.dm index 0f6aec6558b..a4741b16745 100644 --- a/code/modules/modular_computers/computers/machinery/console_presets.dm +++ b/code/modules/modular_computers/computers/machinery/console_presets.dm @@ -1,4 +1,4 @@ -/obj/machinery/modular_computer/console/preset/ +/obj/machinery/modular_computer/console/preset // Can be changed to give devices specific hardware var/_has_id_slot = 0 var/_has_printer = 0 @@ -8,13 +8,14 @@ . = ..() if(!cpu) return - cpu.processor_unit = new/obj/item/weapon/computer_hardware/processor_unit(cpu) + cpu.install_component(new /obj/item/weapon/computer_hardware/processor_unit) + if(_has_id_slot) - cpu.card_slot = new/obj/item/weapon/computer_hardware/card_slot(cpu) + cpu.install_component(new /obj/item/weapon/computer_hardware/card_slot) if(_has_printer) - cpu.nano_printer = new/obj/item/weapon/computer_hardware/nano_printer(cpu) + cpu.install_component(new /obj/item/weapon/computer_hardware/printer) if(_has_battery) - cpu.battery_module = new/obj/item/weapon/computer_hardware/battery_module/super(cpu) + cpu.install_component(new /obj/item/weapon/computer_hardware/battery(cpu, /obj/item/weapon/stock_parts/cell/computer/super)) install_programs() // Override in child types to install preset-specific programs. diff --git a/code/modules/modular_computers/computers/machinery/modular_computer.dm b/code/modules/modular_computers/computers/machinery/modular_computer.dm index 98b29951607..2aada0b5860 100644 --- a/code/modules/modular_computers/computers/machinery/modular_computer.dm +++ b/code/modules/modular_computers/computers/machinery/modular_computer.dm @@ -3,14 +3,14 @@ var/list/global_modular_computers = list() // Modular Computer - device that runs various programs and operates with hardware // DO NOT SPAWN THIS TYPE. Use /laptop/ or /console/ instead. -/obj/machinery/modular_computer/ +/obj/machinery/modular_computer name = "modular computer" desc = "An advanced computer." - 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 + use_power = 1 + idle_power_usage = 5 + 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 @@ -18,61 +18,20 @@ var/list/global_modular_computers = list() icon = null icon_state = null - var/icon_state_unpowered = null // Icon state when the computer is turned off - var/screen_icon_state_menu = "menu" // Icon state overlay when the computer is turned on, but no program is loaded that would override the screen. - 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/icon_state_unpowered = null // Icon state when the computer is turned off. + var/icon_state_powered = null // Icon state when the computer is turned on. + var/screen_icon_state_menu = "menu" // Icon state overlay when the computer is turned on, but no program is loaded that would override the screen. + 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. - -/obj/machinery/modular_computer/attack_ghost(mob/dead/observer/user) - if(cpu) - cpu.attack_ghost(user) - -/obj/machinery/modular_computer/emag_act(mob/user) - return cpu ? cpu.emag_act(user) : 1 - -/obj/machinery/modular_computer/update_icon() - icon_state = icon_state_unpowered - cut_overlays() - - if(!cpu || !cpu.enabled) - if (!(stat & NOPOWER) || battery_powered) - add_overlay(screen_icon_screensaver) - SetLuminosity(0) - return - SetLuminosity(light_strength) - if(cpu.active_program) - add_overlay(cpu.active_program.program_icon_state ? cpu.active_program.program_icon_state : screen_icon_state_menu) - else - overlays.Add(screen_icon_state_menu) - -// Eject ID card from computer, if it has ID slot with card inside. -/obj/machinery/modular_computer/verb/eject_id() - set name = "Eject ID" - set category = "Object" - set src in view(1) - - 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() + var/obj/item/device/modular_computer/processor/cpu = null // CPU that handles most logic while this type only handles power and other specific things. /obj/machinery/modular_computer/New() ..() @@ -86,28 +45,67 @@ var/list/global_modular_computers = list() cpu = null return ..() +/obj/machinery/modular_computer/attack_ghost(mob/dead/observer/user) + if(cpu) + cpu.attack_ghost(user) + +/obj/machinery/modular_computer/emag_act(mob/user) + return cpu ? cpu.emag_act(user) : 1 + +/obj/machinery/modular_computer/update_icon() + cut_overlays() + icon_state = icon_state_powered + + if(!cpu || !cpu.enabled) + if (!(stat & NOPOWER) && (cpu && cpu.use_power())) + add_overlay(screen_icon_screensaver) + else + icon_state = icon_state_unpowered + SetLuminosity(0) + else + SetLuminosity(light_strength) + if(cpu.active_program) + add_overlay(cpu.active_program.program_icon_state ? cpu.active_program.program_icon_state : screen_icon_state_menu) + else + overlays.Add(screen_icon_state_menu) + + if(cpu && cpu.damage > cpu.broken_damage) + add_overlay("bsod") + add_overlay("broken") + +// Eject ID card from computer, if it has ID slot with card inside. +/obj/machinery/modular_computer/verb/eject_id() + set name = "Eject ID" + set category = "Object" + set src in view(1) + + if(cpu) + cpu.eject_id() + +// Eject ID card from computer, if it has ID slot with card inside. +/obj/machinery/modular_computer/verb/eject_disk() + set name = "Eject Data Disk" + set category = "Object" + set src in view(1) + + if(cpu) + cpu.eject_disk() + +/obj/machinery/modular_computer/AltClick(mob/user) + if(cpu) + cpu.AltClick(user) + // 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(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) // Keep names in sync. cpu.name = src.name - cpu.process(1) - -// 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(N) - if(tesla_link && (tesla_link.name == N)) - return tesla_link - return null + cpu.process() // Used in following function to reduce copypaste /obj/machinery/modular_computer/proc/power_failure(malfunction = 0) @@ -115,65 +113,18 @@ var/list/global_modular_computers = list() 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 stat |= NOPOWER update_icon() -// Called by cpu item's process() automatically, handles our power interaction. -/obj/machinery/modular_computer/proc/handle_power() - if(!check_external_power()) - 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) // Not battery run, but lacking APC connection. - power_failure() - return 0 - else if(stat & NOPOWER) - stat &= ~NOPOWER - - if(cpu.battery_module && cpu.battery_module.battery.charge) - battery_powered = 1 - else - battery_powered = 0 - - var/power_usage = cpu.screen_on ? base_active_power_usage : base_idle_power_usage - for(var/C in src.cpu.get_all_components()) - var/obj/item/weapon/computer_hardware/CH = C - if(CH.enabled) - power_usage += CH.power_usage - - // Wireless APC connection exists. - 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 - // Battery is not fully charged. Begin slowly recharging. - if(cpu.battery_module && (cpu.battery_module.battery.charge < cpu.battery_module.battery.maxcharge)) - use_power = 2 - - if(cpu.battery_module && powered() && (use_power == 2)) // Battery charging itself - cpu.battery_module.battery.give(100 * CELLRATE) - else if(cpu.battery_module && !powered()) // Unpowered, but battery covers the usage. - if(!cpu.battery_module.battery.use(idle_power_usage * CELLRATE)) - cpu.battery_module.battery.charge = 0 - power_failure() - - 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 - if(!cpu.battery_module.battery.use(power_usage * CELLRATE)) - cpu.battery_module.battery.charge = 0 - power_failure() - cpu.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() - if(battery_powered) + if(cpu && cpu.use_power()) // If "CPU" still has a power source, PC wouldn't go offline. + stat &= ~NOPOWER + update_icon() return ..() + update_icon() /obj/machinery/modular_computer/attackby(var/obj/item/weapon/W as obj, mob/user) if(cpu) @@ -197,11 +148,4 @@ var/list/global_modular_computers = list() // "Brute" damage mostly damages the casing. /obj/machinery/modular_computer/bullet_act(obj/item/projectile/Proj) if(cpu) - cpu.bullet_act(Proj) - - -/obj/machinery/modular_computer/proc/check_external_power() - if((!powered() || !tesla_link || !tesla_link.enabled || !tesla_link.check_functionality())) - return 0 - else - return 1 \ No newline at end of file + cpu.bullet_act(Proj) \ No newline at end of file diff --git a/code/modules/modular_computers/computers/machinery/modular_console.dm b/code/modules/modular_computers/computers/machinery/modular_console.dm index 5742faa9311..b5b6fe7b143 100644 --- a/code/modules/modular_computers/computers/machinery/modular_console.dm +++ b/code/modules/modular_computers/computers/machinery/modular_console.dm @@ -1,10 +1,11 @@ -/obj/machinery/modular_computer/console/ +/obj/machinery/modular_computer/console name = "console" desc = "A stationary computer." icon = 'icons/obj/modular_console.dmi' icon_state = "console" - icon_state_unpowered = "console" + icon_state_powered = "console" + icon_state_unpowered = "console-off" screen_icon_state_menu = "menu" hardware_flag = PROGRAM_CONSOLE var/console_department = "" // Used in New() to set network tag according to our area. @@ -12,7 +13,7 @@ density = 1 base_idle_power_usage = 100 base_active_power_usage = 500 - max_hardware_size = 3 + max_hardware_size = 4 steel_sheet_cost = 10 light_strength = 2 _max_damage = 300 @@ -21,16 +22,19 @@ /obj/machinery/modular_computer/console/buildable/New() ..() // User-built consoles start as empty frames. - qdel(tesla_link) + qdel(cpu.recharger) qdel(cpu.network_card) qdel(cpu.hard_drive) /obj/machinery/modular_computer/console/New() ..() - cpu.battery_module = null - cpu.network_card = new/obj/item/weapon/computer_hardware/network_card/wired(src) - tesla_link = new/obj/item/weapon/computer_hardware/tesla_link(src) - cpu.hard_drive = new/obj/item/weapon/computer_hardware/hard_drive/super(src) // Consoles generally have better HDDs due to lower space limitations + if(cpu.battery_module) + qdel(cpu.battery_module) + + cpu.install_component(new /obj/item/weapon/computer_hardware/network_card/wired) + cpu.install_component(new /obj/item/weapon/computer_hardware/recharger/APC) + cpu.install_component(new /obj/item/weapon/computer_hardware/hard_drive/super) // Consoles generally have better HDDs due to lower space limitations + var/area/A = get_area(src) // Attempts to set this console's tag according to our area. Since some areas have stuff like "XX - YY" in their names we try to remove that too. if(A && console_department) diff --git a/code/modules/modular_computers/computers/machinery/modular_laptop.dm b/code/modules/modular_computers/computers/machinery/modular_laptop.dm deleted file mode 100644 index 55cb385a4e1..00000000000 --- a/code/modules/modular_computers/computers/machinery/modular_laptop.dm +++ /dev/null @@ -1,110 +0,0 @@ -// Laptop in it's item state, can be carried around. - -/obj/item/laptop - name = "laptop computer" - desc = "A portable computer. It is closed." - icon = 'icons/obj/modular_laptop.dmi' - icon_state = "laptop-closed" - item_state = "laptop-inhand" - w_class = 3 - var/obj/machinery/modular_computer/laptop/stored_computer = null - -/obj/item/laptop/verb/open_computer() - set name = "Open Laptop" - set category = "Object" - set src in view(1) - - if(usr.stat || usr.restrained() || usr.lying || !istype(usr, /mob/living)) - usr << "You can't do that." - return - - if(!Adjacent(usr)) - usr << "You can't reach it." - return - - if(!istype(loc,/turf)) - usr << "[src] is too bulky! You'll have to set it down." - return - - if(!stored_computer) - if(contents.len) - for(var/obj/O in contents) - O.forceMove(src.loc) - usr << "\The [src] crumbles to pieces." - spawn(5) - qdel(src) - return - - stored_computer.forceMove(src.loc) - stored_computer.stat &= ~MAINT - stored_computer.update_icon() - if(stored_computer.cpu) - stored_computer.cpu.screen_on = 1 - loc = stored_computer - usr << "You open \the [src]." - - -/obj/item/laptop/AltClick() - if(Adjacent(usr)) - open_computer() - -// The actual laptop -/obj/machinery/modular_computer/laptop - 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. - 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" - 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() - ..() - // User-built consoles start as empty frames. - qdel(tesla_link) - qdel(cpu.network_card) - qdel(cpu.hard_drive) - -// Close the computer. collapsing it into movable item that can't be used. -/obj/machinery/modular_computer/laptop/verb/close_computer() - set name = "Close Laptop" - set category = "Object" - set src in view(1) - - if(usr.stat || usr.restrained() || usr.lying || !istype(usr, /mob/living)) - usr << "You can't do that." - return - - if(!Adjacent(usr)) - usr << "You can't reach it." - return - - close_laptop(usr) - -/obj/machinery/modular_computer/laptop/proc/close_laptop(mob/user = null) - if(istype(loc,/obj/item/laptop)) - return - if(!istype(loc,/turf)) - return - - if(!portable) - portable=new - portable.stored_computer = src - - portable.forceMove(src.loc) - src.forceMove(portable) - stat |= MAINT - if(user) - user << "You close \the [src]." - if(cpu) - cpu.screen_on = 0 - -/obj/machinery/modular_computer/laptop/AltClick() - if(Adjacent(usr)) - close_laptop() \ No newline at end of file diff --git a/code/modules/modular_computers/file_system/computer_file.dm b/code/modules/modular_computers/file_system/computer_file.dm index c853e7ce0fd..c2b809ad46a 100644 --- a/code/modules/modular_computers/file_system/computer_file.dm +++ b/code/modules/modular_computers/file_system/computer_file.dm @@ -20,8 +20,8 @@ var/global/file_uid = 0 holder.remove_file(src) // holder.holder is the computer that has drive installed. If we are Destroy()ing program that's currently running kill it. - if(holder.holder2 && holder.holder2.active_program == src) - holder.holder2.kill_program(1) + if(holder.holder && holder.holder.active_program == src) + holder.holder.kill_program(forced = TRUE) holder = null ..() diff --git a/code/modules/modular_computers/file_system/program.dm b/code/modules/modular_computers/file_system/program.dm index 87aa3dab1ab..df2967bbd56 100644 --- a/code/modules/modular_computers/file_system/program.dm +++ b/code/modules/modular_computers/file_system/program.dm @@ -5,7 +5,7 @@ var/required_access = null // List of required accesses to *run* the program. var/transfer_access = null // List of required access to download or file host the program var/program_state = PROGRAM_STATE_KILLED// PROGRAM_STATE_KILLED or PROGRAM_STATE_BACKGROUND or PROGRAM_STATE_ACTIVE - specifies whether this program is running. - var/obj/item/modular_computer/computer // Device that runs this program. + var/obj/item/device/modular_computer/computer // Device that runs this program. var/filedesc = "Unknown Program" // User-friendly name of this program. var/extended_desc = "N/A" // Short description of this program's function. var/program_icon_state = null // Program-specific screen icon state @@ -16,10 +16,9 @@ var/network_destination = null // Optional string that describes what NTNet server/system this program connects to. Used in default logging. var/available_on_ntnet = 1 // Whether the program can be downloaded from NTNet. Set to 0 to disable. var/available_on_syndinet = 0 // Whether the program can be downloaded from SyndiNet (accessible via emagging the computer). Set to 1 to enable. - var/computer_emagged = 0 // Set to 1 if computer that's running us was emagged. Computer updates this every Process() tick var/ui_header = null // Example: "something.gif" - a header image that will be rendered in computer's UI when this program is running at background. Images are taken from /icons/program_icons. Be careful not to use too large images! -/datum/computer_file/program/New(obj/item/modular_computer/comp = null) +/datum/computer_file/program/New(obj/item/device/modular_computer/comp = null) ..() if(comp && istype(comp)) computer = comp @@ -78,7 +77,7 @@ if(!access_to_check) // No required_access, allow it. return 1 - if(computer_emagged && !transfer) //emags can bypass the execution locks but not the download ones. + if(computer.emagged && !transfer) //emags can bypass the execution locks but not the download ones. return 1 if(IsAdminGhost(user)) @@ -91,9 +90,8 @@ var/mob/living/carbon/human/h = user var/obj/item/weapon/card/id/I = h.get_idcard() var/obj/item/weapon/card/id/C = h.get_active_hand() - if (istype(C, /obj/item/device/pda)) - var/obj/item/device/pda/pda = C - C = pda.id + if(C) + C = C.GetID() if(!(C && istype(C))) C = null @@ -130,7 +128,7 @@ return 0 // Use this proc to kill the program. Designed to be implemented by each program if it requires on-quit logic, such as the NTNRC client. -/datum/computer_file/program/proc/kill_program(forced = 0) +/datum/computer_file/program/proc/kill_program(forced = FALSE) program_state = PROGRAM_STATE_KILLED if(network_destination) generate_network_log("Connection to [network_destination] closed.") diff --git a/code/modules/modular_computers/file_system/program_events.dm b/code/modules/modular_computers/file_system/program_events.dm index 996d6393722..279d646cfd7 100644 --- a/code/modules/modular_computers/file_system/program_events.dm +++ b/code/modules/modular_computers/file_system/program_events.dm @@ -7,11 +7,11 @@ // Called when the computer fails due to power loss. Override when program wants to specifically react to power loss. /datum/computer_file/program/proc/event_powerfailure(background) - kill_program(1) + kill_program(forced = TRUE) // Called when the network connectivity fails. Computer does necessary checks and only calls this when requires_ntnet_feature and similar variables are not met. /datum/computer_file/program/proc/event_networkfailure(background) - kill_program(1) + kill_program(forced = TRUE) if(background) computer.visible_message("\The [computer]'s screen displays an \"Process [filename].[filetype] (PID [rand(100,999)]) terminated - Network Error\" error") else diff --git a/code/modules/modular_computers/file_system/programs/alarm.dm b/code/modules/modular_computers/file_system/programs/alarm.dm index 3a3c9d72e78..57aef75feb4 100644 --- a/code/modules/modular_computers/file_system/programs/alarm.dm +++ b/code/modules/modular_computers/file_system/programs/alarm.dm @@ -101,6 +101,6 @@ . = ..(user) alarmdisplay += src -/datum/computer_file/program/alarm_monitor/kill_program(forced = 0) +/datum/computer_file/program/alarm_monitor/kill_program(forced = FALSE) alarmdisplay -= src - ..(forced) \ No newline at end of file + ..() \ No newline at end of file diff --git a/code/modules/modular_computers/file_system/programs/antagonist/dos.dm b/code/modules/modular_computers/file_system/programs/antagonist/dos.dm index a3eb9a27354..d14bb885bfe 100644 --- a/code/modules/modular_computers/file_system/programs/antagonist/dos.dm +++ b/code/modules/modular_computers/file_system/programs/antagonist/dos.dm @@ -28,13 +28,13 @@ target = null error = "Connection to destination relay lost." -/datum/computer_file/program/ntnet_dos/kill_program(var/forced) +/datum/computer_file/program/ntnet_dos/kill_program(forced = FALSE) if(target) target.dos_sources.Remove(src) target = null executed = 0 - ..(forced) + ..() /datum/computer_file/program/ntnet_dos/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = default_state) diff --git a/code/modules/modular_computers/file_system/programs/antagonist/revelation.dm b/code/modules/modular_computers/file_system/programs/antagonist/revelation.dm index 91b61d37836..f5ae0766f74 100644 --- a/code/modules/modular_computers/file_system/programs/antagonist/revelation.dm +++ b/code/modules/modular_computers/file_system/programs/antagonist/revelation.dm @@ -26,13 +26,13 @@ computer.visible_message("\The [computer]'s battery explodes in rain of sparks.") var/datum/effect_system/spark_spread/spark_system = new /datum/effect_system/spark_spread spark_system.start() - if(istype(computer, /obj/item/modular_computer/processor)) - var/obj/item/modular_computer/processor/P = computer - if(P.machinery_computer.tesla_link && prob(50)) - qdel(P.machinery_computer.tesla_link) - computer.visible_message("\The [computer]'s tesla link explodes in rain of sparks.") - var/datum/effect_system/spark_spread/spark_system = new /datum/effect_system/spark_spread - spark_system.start() + + if(computer.recharger && prob(50)) + qdel(computer.recharger) + computer.visible_message("\The [computer]'s recharger explodes in rain of sparks.") + var/datum/effect_system/spark_spread/spark_system = new /datum/effect_system/spark_spread + spark_system.start() + /datum/computer_file/program/revelation/ui_act(action, params) if(..()) diff --git a/code/modules/modular_computers/file_system/programs/card.dm b/code/modules/modular_computers/file_system/programs/card.dm index feb688b1d2a..1e201da470b 100644 --- a/code/modules/modular_computers/file_system/programs/card.dm +++ b/code/modules/modular_computers/file_system/programs/card.dm @@ -129,7 +129,7 @@ else show_assignments = 1 if("PRG_print") - if(computer && computer.nano_printer) //This option should never be called if there is no printer + if(computer && computer.printer) //This option should never be called if there is no printer if(mod_mode) if(authorized()) var/contents = {"

Access Report

@@ -145,7 +145,7 @@ if(A in known_access_rights) contents += " [get_access_desc(A)]" - if(!computer.nano_printer.print_text(contents,"access report")) + if(!computer.printer.print_text(contents,"access report")) usr << "Hardware error: Printer was unable to print the file. It may be out of paper." return else @@ -155,7 +155,7 @@
[data_core ? data_core.get_manifest(0) : ""] "} - if(!computer.nano_printer.print_text(contents,text("crew manifest ([])", worldtime2text()))) + if(!computer.printer.print_text(contents,text("crew manifest ([])", worldtime2text()))) usr << "Hardware error: Printer was unable to print the file. It may be out of paper." return else @@ -337,7 +337,7 @@ data["assignments"] = show_assignments if(computer) data["have_id_slot"] = !!computer.card_slot - data["have_printer"] = !!computer.nano_printer + data["have_printer"] = !!computer.printer if(!computer.card_slot && mod_mode == 1) mod_mode = 0 //We can't modify IDs when there is no card reader else diff --git a/code/modules/modular_computers/file_system/programs/configurator.dm b/code/modules/modular_computers/file_system/programs/configurator.dm index e0fd5e2f3cf..6b77cbbd4e6 100644 --- a/code/modules/modular_computers/file_system/programs/configurator.dm +++ b/code/modules/modular_computers/file_system/programs/configurator.dm @@ -12,7 +12,7 @@ size = 4 available_on_ntnet = 0 requires_ntnet = 0 - var/obj/item/modular_computer/movable = null + var/obj/item/device/modular_computer/movable = null /datum/computer_file/program/computerconfig/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = default_state) @@ -28,7 +28,6 @@ ui.set_autoupdate(state = 1) /datum/computer_file/program/computerconfig/ui_data(mob/user) - movable = computer if(!istype(movable)) movable = null @@ -37,26 +36,21 @@ if(!movable) return 0 - var/list/data = list() - - - data = get_header_data() - - var/list/hardware = movable.get_all_components() + var/list/data = get_header_data() 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_module ? 1 : 0 - if(movable.battery_module) + if(movable.battery_module && movable.battery_module.battery) data["battery_rating"] = movable.battery_module.battery.maxcharge data["battery_percent"] = round(movable.battery_module.battery.percent()) - if(movable.battery_module) + if(movable.battery_module && movable.battery_module.battery) data["battery"] = list("max" = movable.battery_module.battery.maxcharge, "charge" = round(movable.battery_module.battery.charge)) var/list/all_entries[0] - for(var/I in hardware) + for(var/I in movable.all_components) var/obj/item/weapon/computer_hardware/H = I all_entries.Add(list(list( "name" = H.name, diff --git a/code/modules/modular_computers/file_system/programs/file_browser.dm b/code/modules/modular_computers/file_system/programs/file_browser.dm index 1ae58135aac..254f09b694a 100644 --- a/code/modules/modular_computers/file_system/programs/file_browser.dm +++ b/code/modules/modular_computers/file_system/programs/file_browser.dm @@ -14,6 +14,9 @@ if(..()) return 1 + var/obj/item/weapon/computer_hardware/hard_drive/HDD = computer.hard_drive + var/obj/item/weapon/computer_hardware/hard_drive/RHDD = computer.portable_drive + switch(action) if("PRG_openfile") . = 1 @@ -23,7 +26,6 @@ var/newname = sanitize(input(usr, "Enter file name or leave blank to cancel:", "File rename")) if(!newname) return 1 - var/obj/item/weapon/computer_hardware/hard_drive/HDD = computer.hard_drive if(!HDD) return 1 var/datum/computer_file/data/F = new/datum/computer_file/data() @@ -32,7 +34,6 @@ HDD.store_file(F) if("PRG_deletefile") . = 1 - var/obj/item/weapon/computer_hardware/hard_drive/HDD = computer.hard_drive if(!HDD) return 1 var/datum/computer_file/file = HDD.find_file_by_name(params["name"]) @@ -41,7 +42,6 @@ HDD.remove_file(file) if("PRG_usbdeletefile") . = 1 - var/obj/item/weapon/computer_hardware/hard_drive/RHDD = computer.portable_drive if(!RHDD) return 1 var/datum/computer_file/file = RHDD.find_file_by_name(params["name"]) @@ -54,7 +54,6 @@ error = null if("PRG_clone") . = 1 - var/obj/item/weapon/computer_hardware/hard_drive/HDD = computer.hard_drive if(!HDD) return 1 var/datum/computer_file/F = HDD.find_file_by_name(params["name"]) @@ -64,7 +63,6 @@ HDD.store_file(C) if("PRG_rename") . = 1 - var/obj/item/weapon/computer_hardware/hard_drive/HDD = computer.hard_drive if(!HDD) return 1 var/datum/computer_file/file = HDD.find_file_by_name(params["name"]) @@ -77,7 +75,6 @@ . = 1 if(!open_file) return 1 - var/obj/item/weapon/computer_hardware/hard_drive/HDD = computer.hard_drive if(!HDD) return 1 var/datum/computer_file/data/F = HDD.find_file_by_name(open_file) @@ -104,36 +101,31 @@ . = 1 if(!open_file) return 1 - var/obj/item/weapon/computer_hardware/hard_drive/HDD = computer.hard_drive if(!HDD) return 1 var/datum/computer_file/data/F = HDD.find_file_by_name(open_file) if(!F || !istype(F)) return 1 - if(!computer.nano_printer) + if(!computer.printer) error = "Missing Hardware: Your computer does not have required hardware to complete this operation." return 1 - if(!computer.nano_printer.print_text(parse_tags(F.stored_data))) + if(!computer.printer.print_text(parse_tags(F.stored_data))) error = "Hardware error: Printer was unable to print the file. It may be out of paper." return 1 if("PRG_copytousb") . = 1 - var/obj/item/weapon/computer_hardware/hard_drive/HDD = computer.hard_drive - var/obj/item/weapon/computer_hardware/hard_drive/portable/RHDD = computer.portable_drive if(!HDD || !RHDD) return 1 - var/datum/computer_file/F = HDD.find_file_by_name(params) + var/datum/computer_file/F = HDD.find_file_by_name(params["name"]) if(!F || !istype(F)) return 1 var/datum/computer_file/C = F.clone(0) RHDD.store_file(C) if("PRG_copyfromusb") . = 1 - var/obj/item/weapon/computer_hardware/hard_drive/HDD = computer.hard_drive - var/obj/item/weapon/computer_hardware/hard_drive/portable/RHDD = computer.portable_drive if(!HDD || !RHDD) return 1 - var/datum/computer_file/F = RHDD.find_file_by_name(params) + var/datum/computer_file/F = RHDD.find_file_by_name(params["name"]) if(!F || !istype(F)) return 1 var/datum/computer_file/C = F.clone(0) diff --git a/code/modules/modular_computers/file_system/programs/ntdownloader.dm b/code/modules/modular_computers/file_system/programs/ntdownloader.dm index a34163f8eef..32d8d2eba13 100644 --- a/code/modules/modular_computers/file_system/programs/ntdownloader.dm +++ b/code/modules/modular_computers/file_system/programs/ntdownloader.dm @@ -15,7 +15,7 @@ var/download_completion = 0 //GQ of downloaded data. var/download_netspeed = 0 var/downloaderror = "" - var/obj/item/modular_computer/my_computer = null + var/obj/item/device/modular_computer/my_computer = null /datum/computer_file/program/ntnetdownload/proc/begin_file_download(filename) if(downloaded_file) @@ -27,10 +27,10 @@ return 0 // Attempting to download antag only program, but without having emagged computer. No. - if(PRG.available_on_syndinet && !computer_emagged) + if(PRG.available_on_syndinet && !computer.emagged) return 0 - if(!computer || !computer.hard_drive || !computer.hard_drive.try_store_file(PRG)) + if(!computer || !computer.hard_drive || !computer.hard_drive.can_store_file(PRG)) return 0 ui_header = "downloader_running.gif" @@ -50,7 +50,7 @@ /datum/computer_file/program/ntnetdownload/proc/abort_file_download() if(!downloaded_file) return - generate_network_log("Aborted download of file [hacked_download ? "**ENCRYPTED**" : downloaded_file.filename].[downloaded_file.filetype].") + generate_network_log("Aborted download of file [hacked_download ? "**ENCRYPTED**" : "[downloaded_file.filename].[downloaded_file.filetype]"].") downloaded_file = null download_completion = 0 ui_header = "downloader_finished.gif" @@ -58,7 +58,7 @@ /datum/computer_file/program/ntnetdownload/proc/complete_file_download() if(!downloaded_file) return - generate_network_log("Completed download of file [hacked_download ? "**ENCRYPTED**" : downloaded_file.filename].[downloaded_file.filetype].") + generate_network_log("Completed download of file [hacked_download ? "**ENCRYPTED**" : "[downloaded_file.filename].[downloaded_file.filetype]"].") if(!computer || !computer.hard_drive || !computer.hard_drive.store_file(downloaded_file)) // The download failed downloaderror = "I/O ERROR - Unable to save file. Check whether you have enough free space on your hard drive and whether your hard drive is properly connected. If the issue persists contact your system administrator for assistance." @@ -101,7 +101,6 @@ return 0 /datum/computer_file/program/ntnetdownload/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = default_state) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) if (!ui) @@ -113,7 +112,6 @@ ui.set_autoupdate(state = 1) /datum/computer_file/program/ntnetdownload/ui_data(mob/user) - my_computer = computer if(!istype(my_computer)) @@ -146,7 +144,7 @@ "size" = P.size ))) data["hackedavailable"] = 0 - if(computer_emagged) // If we are running on emagged computer we have access to some "bonus" software + if(computer.emagged) // If we are running on emagged computer we have access to some "bonus" software var/list/hacked_programs[0] for(var/S in ntnet_global.available_antag_software) var/datum/computer_file/program/P = S @@ -161,4 +159,4 @@ data["downloadable_programs"] = all_entries - return data \ No newline at end of file + return data diff --git a/code/modules/modular_computers/file_system/programs/ntnrc_client.dm b/code/modules/modular_computers/file_system/programs/ntnrc_client.dm index e8cbe357113..b559e9d161f 100644 --- a/code/modules/modular_computers/file_system/programs/ntnrc_client.dm +++ b/code/modules/modular_computers/file_system/programs/ntnrc_client.dm @@ -173,11 +173,11 @@ else ui_header = "ntnrc_idle.gif" -/datum/computer_file/program/chatclient/kill_program(forced = 0) +/datum/computer_file/program/chatclient/kill_program(forced = FALSE) if(channel) channel.remove_client(src) channel = null - ..(forced) + ..() /datum/computer_file/program/chatclient/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = default_state) diff --git a/code/modules/modular_computers/file_system/programs/nttransfer.dm b/code/modules/modular_computers/file_system/programs/nttransfer.dm index d9d0c6b8a30..bec4a6d532e 100644 --- a/code/modules/modular_computers/file_system/programs/nttransfer.dm +++ b/code/modules/modular_computers/file_system/programs/nttransfer.dm @@ -44,7 +44,7 @@ var/global/nttransfer_uid = 0 if(!remote) crash_download("Connection to remote server lost") -/datum/computer_file/program/nttransfer/kill_program(forced = 0) +/datum/computer_file/program/nttransfer/kill_program(forced = FALSE) if(downloaded_file) // Client mode, clean up variables for next use finalize_download() @@ -170,7 +170,7 @@ var/global/nttransfer_uid = 0 data["uploading"] = 1 data["upload_uid"] = unique_token data["upload_clients"] = connected_clients.len - data["upload_haspassword"] = server_password ? 1 : 0 + data["haspassword"] = server_password ? 1 : 0 data["upload_filename"] = "[provided_file.filename].[provided_file.filetype]" else if (upload_menu) var/list/all_files[0] diff --git a/code/modules/modular_computers/hardware/CPU.dm b/code/modules/modular_computers/hardware/CPU.dm new file mode 100644 index 00000000000..e78f02d85cc --- /dev/null +++ b/code/modules/modular_computers/hardware/CPU.dm @@ -0,0 +1,40 @@ +// CPU that allows the computer to run programs. +// Better CPUs are obtainable via research and can run more programs on background. + +/obj/item/weapon/computer_hardware/processor_unit + name = "processor board" + desc = "A standard CPU board used in most computers. It can run up to three programs simultaneously." + icon_state = "cpuboard" + w_class = 2 + power_usage = 50 + critical = 1 + malfunction_probability = 1 + origin_tech = "programming=3;engineering=2" + var/max_idle_programs = 2 // 2 idle, + 1 active = 3 as said in description. + +/obj/item/weapon/computer_hardware/processor_unit/small + name = "microprocessor" + desc = "A miniaturised CPU used in portable devices. It can run up to two programs simultaneously." + icon_state = "cpu" + w_class = 1 + power_usage = 25 + max_idle_programs = 1 + origin_tech = "programming=2;engineering=2" + +/obj/item/weapon/computer_hardware/processor_unit/photonic + name = "photonic processor board" + desc = "An advanced experimental CPU board that uses photonic core instead of regular circuitry. It can run up to five programs simultaneously, but uses a lot of power." + icon_state = "cpuboard_super" + w_class = 2 + power_usage = 250 + max_idle_programs = 4 + origin_tech = "programming=5;engineering=4" + +/obj/item/weapon/computer_hardware/processor_unit/photonic/small + name = "photonic microprocessor" + desc = "An advanced miniaturised CPU for use in portable devices. It uses photonic core instead of regular circuitry. It can run up to three programs simultaneously." + icon_state = "cpu_super" + w_class = 1 + power_usage = 75 + max_idle_programs = 2 + origin_tech = "programming=4;engineering=3" \ No newline at end of file diff --git a/code/modules/modular_computers/hardware/_hardware.dm b/code/modules/modular_computers/hardware/_hardware.dm new file mode 100644 index 00000000000..ebbef88c2d0 --- /dev/null +++ b/code/modules/modular_computers/hardware/_hardware.dm @@ -0,0 +1,108 @@ +/obj/item/weapon/computer_hardware + name = "hardware" + desc = "Unknown Hardware." + icon = 'icons/obj/module.dmi' + icon_state = "std_mod" + + w_class = 1 // w_class limits which devices can contain this component. + // 1: PDAs/Tablets, 2: Laptops, 3-4: Consoles only + var/obj/item/device/modular_computer/holder = null + // Computer that holds this hardware, if any. + + 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 = 0 // Prevent disabling for important component, like the CPU. + var/can_install = 1 // Prevents direct installation of removable media. + 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/New(var/obj/L) + ..() + pixel_x = rand(-8, 8) + pixel_y = rand(-8, 8) + +/obj/item/weapon/computer_hardware/Destroy() + if(holder) + holder.uninstall_component(src) + return ..() + + +/obj/item/weapon/computer_hardware/attackby(obj/item/I, mob/living/user) + // Multitool. Runs diagnostics + if(istype(I, /obj/item/device/multitool)) + user << "***** DIAGNOSTICS REPORT *****" + diagnostics(user) + user << "******************************" + return 1 + + // Cable coil. Works as repair method, but will probably require multiple applications and more cable. + if(istype(I, /obj/item/stack/cable_coil)) + var/obj/item/stack/S = I + 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 [I]." + take_damage(-10) + return 1 + + if(try_insert(I, user)) + 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"]" + +// Handles damage checks +/obj/item/weapon/computer_hardware/proc/check_functionality() + if(!enabled) // Disabled. + return FALSE + + if(damage > damage_failure) // Too damaged to work at all. + return FALSE + + if(damage > damage_malfunction) // Still working. Well, sometimes... + if(prob(malfunction_probability)) + return FALSE + + return TRUE // Good to go. + +/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 = max(0, min(damage, max_damage)) // Clamp the value. + + +// Component-side compatibility check. +/obj/item/weapon/computer_hardware/proc/can_install(obj/item/device/modular_computer/M, mob/living/user = null) + return can_install + +// Called when component is installed into PC. +/obj/item/weapon/computer_hardware/proc/on_install(obj/item/device/modular_computer/M, mob/living/user = null) + return + +// Called when component is removed from PC. +/obj/item/weapon/computer_hardware/proc/on_remove(obj/item/device/modular_computer/M, mob/living/user = null) + try_eject() + +// Called when someone tries to insert something in it - paper in printer, card in card reader, etc. +/obj/item/weapon/computer_hardware/proc/try_insert(obj/item/I, mob/living/user = null) + return FALSE + +// Called when someone tries to eject something from it - card from card reader, etc. +/obj/item/weapon/computer_hardware/proc/try_eject(slot=0, mob/living/user = null) + return FALSE diff --git a/code/modules/modular_computers/hardware/battery_module.dm b/code/modules/modular_computers/hardware/battery_module.dm index e46fd6f1929..824cd03bf21 100644 --- a/code/modules/modular_computers/hardware/battery_module.dm +++ b/code/modules/modular_computers/hardware/battery_module.dm @@ -1,81 +1,98 @@ -// This device is wrapper for actual power cell. I have decided to not use power cells directly as even low-end cells available on station -// have tremendeous capacity in comparsion. Higher tier cells would provide your device with nearly infinite battery life, which is something i want to avoid. -/obj/item/weapon/computer_hardware/battery_module - name = "standard battery" - 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" +/obj/item/weapon/computer_hardware/battery + name = "power cell controller" + desc = "A charge controller for standard power cells, used in all kinds of modular computers." + icon_state = "cell_con" critical = 1 malfunction_probability = 1 - origin_tech = list("powerstorage" = 1, "engineering" = 1) - var/battery_rating = 750 + origin_tech = "powerstorage=1;engineering=1" var/obj/item/weapon/stock_parts/cell/battery = null -/obj/item/weapon/computer_hardware/battery_module/advanced - name = "advanced battery" - desc = "An advanced power cell, often used in most laptops. It is too large to be fitted into smaller devices. It's rating is 1100." - icon_state = "battery_advanced" - origin_tech = list("powerstorage" = 2, "engineering" = 2) - hardware_size = 2 - battery_rating = 1100 - -/obj/item/weapon/computer_hardware/battery_module/super - name = "super battery" - desc = "A very advanced power cell, often used in high-end devices, or as uninterruptable power supply for important consoles or servers. It's rating is 1500." - icon_state = "battery_super" - origin_tech = list("powerstorage" = 3, "engineering" = 3) - hardware_size = 2 - battery_rating = 1500 - -/obj/item/weapon/computer_hardware/battery_module/ultra - name = "ultra battery" - desc = "A very advanced large power cell. It's often used as uninterruptable power supply for critical consoles or servers. It's rating is 2000." - icon_state = "battery_ultra" - origin_tech = list("powerstorage" = 5, "engineering" = 4) - hardware_size = 3 - battery_rating = 2000 - -/obj/item/weapon/computer_hardware/battery_module/micro - name = "micro battery" - desc = "A small power cell, commonly seen in most portable microcomputers. It's rating is 500." - icon_state = "battery_micro" - origin_tech = list("powerstorage" = 2, "engineering" = 2) - battery_rating = 500 - -/obj/item/weapon/computer_hardware/battery_module/nano - name = "nano battery" - desc = "A tiny power cell, commonly seen in low-end portable microcomputers. It's rating is 300." - icon_state = "battery_nano" - origin_tech = list("powerstorage" = 1, "engineering" = 1) - battery_rating = 300 - -// This is not intended to be obtainable in-game. Intended for adminbus and debugging purposes. -/obj/item/weapon/computer_hardware/battery_module/lambda - name = "lambda coil" - desc = "A very complex device that creates it's own bluespace dimension. This dimension may be used to store massive amounts of energy." - icon_state = "battery_lambda" - 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/stock_parts/cell(src) - battery.maxcharge = battery_rating - battery.charge = battery.maxcharge/2 +/obj/item/weapon/computer_hardware/battery/New(loc, battery_type = null) + if(battery_type) + battery = new battery_type(src) ..() -/obj/item/weapon/computer_hardware/battery_module/proc/charge_to_full() +/obj/item/weapon/computer_hardware/battery/try_insert(obj/item/I, mob/living/user = null) + if(!holder) + return FALSE + + if(!istype(I, /obj/item/weapon/stock_parts/cell)) + return FALSE + if(battery) - battery.charge = battery.maxcharge + user << "You try to connect \the [I] to \the [src], but it's connectors are occupied." + return FALSE -/obj/item/weapon/computer_hardware/battery_module/try_install_component(mob/living/user, obj/item/modular_computer/M, found = 0) - if(!user.drop_item(src)) - return - if(M.battery_module) - user << "This computer's battery slot is already occupied by \the [M.battery_module]." - return - found = 1 - M.battery_module = src - ..(user, M, found) \ No newline at end of file + if(I.w_class > holder.max_hardware_size) + user << "This power cell is too large for \the [holder]!" + return FALSE + + if(user && !user.unEquip(I)) + return FALSE + + battery = I + I.forceMove(src) + user << "You connect \the [I] to \the [src]." + + return TRUE + + +/obj/item/weapon/computer_hardware/battery/try_eject(slot=0, mob/living/user = null) + if(!battery) + user << "There is no power cell connected to \the [src]." + return FALSE + else + battery.forceMove(get_turf(src)) + user << "You detach \the [battery] from \the [src]." + battery = null + + if(holder) + if(holder.enabled && !holder.use_power()) + holder.shutdown_computer() + + return TRUE + return FALSE + + + + + + + +/obj/item/weapon/stock_parts/cell/computer + name = "standard battery" + desc = "A standard power cell, commonly seen in high-end portable microcomputers or low-end laptops." + icon = 'icons/obj/module.dmi' + icon_state = "cell_mini" + origin_tech = "powerstorage=2;engineering=1" + w_class = 1 + maxcharge = 750 + + +/obj/item/weapon/stock_parts/cell/computer/advanced + name = "advanced battery" + desc = "An advanced power cell, often used in most laptops. It is too large to be fitted into smaller devices." + icon_state = "cell" + origin_tech = "powerstorage=2;engineering=2" + w_class = 2 + maxcharge = 1500 + +/obj/item/weapon/stock_parts/cell/computer/super + name = "super battery" + desc = "An advanced power cell, often used in high-end laptops." + icon_state = "cell" + origin_tech = "powerstorage=3;engineering=3" + w_class = 2 + maxcharge = 2000 + +/obj/item/weapon/stock_parts/cell/computer/micro + name = "micro battery" + desc = "A small power cell, commonly seen in most portable microcomputers." + icon_state = "cell_micro" + maxcharge = 500 + +/obj/item/weapon/stock_parts/cell/computer/nano + name = "nano battery" + desc = "A tiny power cell, commonly seen in low-end portable microcomputers." + icon_state = "cell_micro" + maxcharge = 300 \ No newline at end of file diff --git a/code/modules/modular_computers/hardware/card_slot.dm b/code/modules/modular_computers/hardware/card_slot.dm index 17bdaaba623..f0fb2cd20c2 100644 --- a/code/modules/modular_computers/hardware/card_slot.dm +++ b/code/modules/modular_computers/hardware/card_slot.dm @@ -1,31 +1,84 @@ /obj/item/weapon/computer_hardware/card_slot - name = "RFID card slot" - desc = "Slot that allows this computer to write data on RFID cards. Necessary for some programs to run properly." + name = "\improper ID authentication module" + desc = "A module allowing this computer to read or write data on ID cards. Necessary for some programs to run properly." power_usage = 10 //W - critical = 0 - icon_state = "cardreader" - hardware_size = 1 - origin_tech = list("programming" = 2) + icon_state = "card_mini" + w_class = 1 + origin_tech = "programming=2" var/obj/item/weapon/card/id/stored_card = null var/obj/item/weapon/card/id/stored_card2 = null /obj/item/weapon/computer_hardware/card_slot/Destroy() - if(holder2 && (holder2.card_slot == src)) - holder2.card_slot = null - if(stored_card) - stored_card.forceMove(get_turf(holder2)) - if(stored_card2) - stored_card2.forceMove(get_turf(holder2)) - holder2 = null - ..() + try_eject() + return ..() -/obj/item/weapon/computer_hardware/card_slot/try_install_component(mob/living/user, obj/item/modular_computer/M, found = 0) - if(!user.drop_item(src)) - return - if(M.card_slot) - user << "This computer's card slot is already occupied by \the [M.card_slot]." - return - found = 1 - M.card_slot = src - ..(user, M, found) \ No newline at end of file +/obj/item/weapon/computer_hardware/card_slot/GetAccess() + if(stored_card && stored_card2) // Best of both worlds + return (stored_card.GetAccess() | stored_card2.GetAccess()) + else if(stored_card) + return stored_card.GetAccess() + else if(stored_card2) + return stored_card2.GetAccess() + return ..() + +/obj/item/weapon/computer_hardware/card_slot/GetID() + if(stored_card) + return stored_card + else if(stored_card2) + return stored_card2 + return ..() + +/obj/item/weapon/computer_hardware/card_slot/try_insert(obj/item/I, mob/living/user = null) + if(!holder) + return FALSE + + if(!istype(I, /obj/item/weapon/card/id)) + return FALSE + + if(stored_card && stored_card2) + user << "You try to insert \the [I] into \the [src], but it's slots are occupied." + return FALSE + if(user && !user.unEquip(I)) + return FALSE + + if(!stored_card) + stored_card = I + else + stored_card2 = I + I.forceMove(src) + user << "You insert \the [I] into \the [src]." + + return TRUE + + +/obj/item/weapon/computer_hardware/card_slot/try_eject(slot=0, mob/living/user = null) + if(!stored_card && !stored_card2) + user << "There are no cards in \the [src]." + return FALSE + + var/ejected = 0 + if(stored_card && (!slot || slot == 1)) + stored_card.forceMove(get_turf(src)) + stored_card.verb_pickup() + stored_card = null + ejected++ + + if(stored_card2 && (!slot || slot == 2)) + stored_card2.forceMove(get_turf(src)) + stored_card2.verb_pickup() + stored_card2 = null + ejected++ + + if(ejected) + if(holder) + if(holder.active_program) + holder.active_program.event_idremoved(0, slot) + + for(var/I in holder.idle_threads) + var/datum/computer_file/program/P = I + P.event_idremoved(1, slot) + + user << "You remove the card[ejected>1 ? "s" : ""] from \the [src]." + return TRUE + return FALSE diff --git a/code/modules/modular_computers/hardware/hard_drive.dm b/code/modules/modular_computers/hardware/hard_drive.dm index 4bbfb8c266e..e5e43f57283 100644 --- a/code/modules/modular_computers/hardware/hard_drive.dm +++ b/code/modules/modular_computers/hardware/hard_drive.dm @@ -1,59 +1,23 @@ -/obj/item/weapon/computer_hardware/hard_drive/ - name = "basic hard drive" - desc = "A small power efficient solid state drive, with 128GQ of storage capacity for use in basic computers where power efficiency is desired." - power_usage = 25 // SSD or something with low power usage - icon_state = "hdd_normal" - hardware_size = 1 - origin_tech = list("programming" = 1, "engineering" = 1) +/obj/item/weapon/computer_hardware/hard_drive + name = "hard disk drive" + desc = "A small HDD, for use in basic computers where power efficiency is desired." + power_usage = 25 + icon_state = "harddisk_mini" + critical = 1 + w_class = 1 + origin_tech = "programming=1;engineering=1" var/max_capacity = 128 var/used_capacity = 0 var/list/stored_files = list() // List of stored files on this drive. DO NOT MODIFY DIRECTLY! -/obj/item/weapon/computer_hardware/hard_drive/advanced - name = "advanced hard drive" - desc = "A small hybrid hard drive with 256GQ of storage capacity for use in higher grade computers where balance between power efficiency and capacity is desired." - max_capacity = 256 - origin_tech = list("programming" = 2, "engineering" = 2) - power_usage = 50 // Hybrid, medium capacity and medium power storage - icon_state = "hdd_advanced" - hardware_size = 2 +/obj/item/weapon/computer_hardware/hard_drive/proc/install_default_programs() + store_file(new/datum/computer_file/program/computerconfig(src)) // Computer configuration utility, allows hardware control and displays more info than status bar + store_file(new/datum/computer_file/program/ntnetdownload(src)) // NTNet Downloader Utility, allows users to download more software from NTNet repository + store_file(new/datum/computer_file/program/filemanager(src)) // File manager, allows text editor functions and basic file manipulation. -/obj/item/weapon/computer_hardware/hard_drive/super - name = "super hard drive" - desc = "A small hard drive with 512GQ of storage capacity for use in cluster storage solutions where capacity is more important than power efficiency." - max_capacity = 512 - origin_tech = list("programming" = 3, "engineering" = 3) - power_usage = 100 // High-capacity but uses lots of power, shortening battery life. Best used with APC link. - icon_state = "hdd_super" - hardware_size = 2 - -/obj/item/weapon/computer_hardware/hard_drive/cluster - name = "cluster hard drive" - desc = "A large storage cluster consisting of multiple hard drives for usage in high capacity storage systems. Has capacity of 2048 GQ." - power_usage = 500 - origin_tech = list("programming" = 4, "engineering" = 4) - max_capacity = 2048 - icon_state = "hdd_cluster" - hardware_size = 3 - -// For tablets, etc. - highly power efficient. -/obj/item/weapon/computer_hardware/hard_drive/small - name = "small hard drive" - desc = "A small highly efficient solid state drive for portable devices." - power_usage = 10 - origin_tech = list("programming" = 2, "engineering" = 2) - max_capacity = 64 - icon_state = "hdd_small" - hardware_size = 1 - -/obj/item/weapon/computer_hardware/hard_drive/micro - name = "micro hard drive" - desc = "A small micro hard drive for portable devices." - power_usage = 2 - origin_tech = list("programming" = 1, "engineering" = 1) - max_capacity = 32 - icon_state = "hdd_micro" - hardware_size = 1 +/obj/item/weapon/computer_hardware/hard_drive/examine(user) + ..() + user << "It has [max_capacity] GQ of storage capacity." /obj/item/weapon/computer_hardware/hard_drive/diagnostics(var/mob/user) ..() @@ -66,7 +30,7 @@ if(!F || !istype(F)) return 0 - if(!can_store_file(F.size)) + if(!can_store_file(F)) return 0 if(!check_functionality()) @@ -84,13 +48,6 @@ recalculate_size() return 1 -// 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/install_default_programs() - store_file(new/datum/computer_file/program/computerconfig(src)) // Computer configuration utility, allows hardware control and displays more info than status bar - store_file(new/datum/computer_file/program/ntnetdownload(src)) // NTNet Downloader Utility, allows users to download more software from NTNet repository - store_file(new/datum/computer_file/program/filemanager(src)) // File manager, allows text editor functions and basic file manipulation. - - // Use this proc to remove file from the drive. Returns 1 on success and 0 on failure. Contains necessary sanity checks. /obj/item/weapon/computer_hardware/hard_drive/proc/remove_file(var/datum/computer_file/F) if(!F || !istype(F)) @@ -117,27 +74,27 @@ used_capacity = total_size -// Checks whether file can be stored on the hard drive. -/obj/item/weapon/computer_hardware/hard_drive/proc/can_store_file(var/size = 1) - // In the unlikely event someone manages to create that many files. - // BYOND is acting weird with numbers above 999 in loops (infinite loop prevention) - if(stored_files.len >= 999) - return 0 - if(used_capacity + size > max_capacity) - return 0 - else - return 1 - -// Checks whether we can store the file. We can only store unique files, so this checks whether we wouldn't get a duplicity by adding a file. -/obj/item/weapon/computer_hardware/hard_drive/proc/try_store_file(var/datum/computer_file/F) +// Checks whether file can be stored on the hard drive. We can only store unique files, so this checks whether we wouldn't get a duplicity by adding a file. +/obj/item/weapon/computer_hardware/hard_drive/proc/can_store_file(var/datum/computer_file/F) if(!F || !istype(F)) return 0 + + if(F in stored_files) + return 0 + var/name = F.filename + "." + F.filetype for(var/datum/computer_file/file in stored_files) if((file.filename + "." + file.filetype) == name) return 0 - return can_store_file(F.size) + // In the unlikely event someone manages to create that many files. + // BYOND is acting weird with numbers above 999 in loops (infinite loop prevention) + if(stored_files.len >= 999) + return 0 + if((used_capacity + F.size) > max_capacity) + return 0 + else + return 1 // Tries to find the file by filename. Returns null on failure @@ -157,21 +114,56 @@ return null /obj/item/weapon/computer_hardware/hard_drive/Destroy() - if(holder2 && (holder2.hard_drive == src)) - holder2.hard_drive = null stored_files = null - ..() + return ..() /obj/item/weapon/computer_hardware/hard_drive/New() install_default_programs() ..() -/obj/item/weapon/computer_hardware/hard_drive/try_install_component(mob/living/user, obj/item/modular_computer/M, found = 0) - if(!user.drop_item(src)) - return - if(M.hard_drive) - user << "This computer's hard drive slot is already occupied by \the [M.hard_drive]." - return - found = 1 - M.hard_drive = src - ..(user, M, found) \ No newline at end of file + +/obj/item/weapon/computer_hardware/hard_drive/advanced + name = "advanced hard disk drive" + desc = "A hybrid HDD, for use in higher grade computers where balance between power efficiency and capacity is desired." + max_capacity = 256 + origin_tech = "programming=2;engineering=2" + power_usage = 50 // Hybrid, medium capacity and medium power storage + icon_state = "harddisk_mini" + w_class = 2 + +/obj/item/weapon/computer_hardware/hard_drive/super + name = "super hard disk drive" + desc = "A high capacity HDD, for use in cluster storage solutions where capacity is more important than power efficiency." + max_capacity = 512 + origin_tech = "programming=3;engineering=3" + power_usage = 100 // High-capacity but uses lots of power, shortening battery life. Best used with APC link. + icon_state = "harddisk_mini" + w_class = 2 + +/obj/item/weapon/computer_hardware/hard_drive/cluster + name = "cluster hard disk drive" + desc = "A large storage cluster consisting of multiple HDDs for usage in dedicated storage systems." + power_usage = 500 + origin_tech = "programming=4;engineering=4" + max_capacity = 2048 + icon_state = "harddisk" + w_class = 3 + +// For tablets, etc. - highly power efficient. +/obj/item/weapon/computer_hardware/hard_drive/small + name = "solid state drive" + desc = "An efficient SSD for portable devices." + power_usage = 10 + origin_tech = "programming=2;engineering=2" + max_capacity = 64 + icon_state = "ssd_mini" + w_class = 1 + +/obj/item/weapon/computer_hardware/hard_drive/micro + name = "micro solid state drive" + desc = "A highly efficient SSD chip for portable devices." + power_usage = 2 + origin_tech = "programming=1;engineering=1" + max_capacity = 32 + icon_state = "ssd_micro" + w_class = 1 \ No newline at end of file diff --git a/code/modules/modular_computers/hardware/hardware.dm b/code/modules/modular_computers/hardware/hardware.dm deleted file mode 100644 index 4b0d378286a..00000000000 --- a/code/modules/modular_computers/hardware/hardware.dm +++ /dev/null @@ -1,99 +0,0 @@ -/obj/item/weapon/computer_hardware/ - name = "Hardware" - 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/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/sheet/glass)) - 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) - holder2 = C.cpu - return - if(istype(L, /obj/item/modular_computer)) - holder2 = L - return - -/obj/item/weapon/computer_hardware/Destroy() - holder2 = null - 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 = max(0, min(damage, max_damage)) // Clamp the value. - -// Attempts to install the hardware into apropriate slot. -/obj/item/weapon/computer_hardware/proc/try_install_component(mob/living/user, obj/item/modular_computer/M, found = 0) - if(found) - user << "You install \the [src] into \the [M]" - holder2 = M - if(!user.drop_item(src)) - return - forceMove(M) \ No newline at end of file diff --git a/code/modules/modular_computers/hardware/nano_printer.dm b/code/modules/modular_computers/hardware/nano_printer.dm deleted file mode 100644 index ad61db9e671..00000000000 --- a/code/modules/modular_computers/hardware/nano_printer.dm +++ /dev/null @@ -1,62 +0,0 @@ -/obj/item/weapon/computer_hardware/nano_printer - name = "nano printer" - desc = "Small integrated printer with paper recycling module." - power_usage = 50 - origin_tech = list("programming" = 2, "engineering" = 2) - critical = 0 - icon_state = "printer" - hardware_size = 1 - var/stored_paper = 5 - var/max_paper = 10 - -/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 - - var/obj/item/weapon/paper/P = new/obj/item/weapon/paper(get_turf(holder2)) - - // 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() - stored_paper-- - P = null - return 1 - -/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 - - 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 - holder2 = null - ..() - -/obj/item/weapon/computer_hardware/nano_printer/try_install_component(mob/living/user, obj/item/modular_computer/M, found = 0) - if(!user.drop_item(src)) - return - if(M.nano_printer) - user << "This computer's nano printer slot is already occupied by \the [M.nano_printer]." - return - found = 1 - M.nano_printer = src - ..(user, M, found) \ 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 08f1dfcd64a..681dbd503da 100644 --- a/code/modules/modular_computers/hardware/network_card.dm +++ b/code/modules/modular_computers/hardware/network_card.dm @@ -1,13 +1,11 @@ var/global/ntnet_card_uid = 1 -/obj/item/weapon/computer_hardware/network_card/ - name = "basic NTNet network card" - desc = "A basic network card for usage with standard NTNet frequencies." +/obj/item/weapon/computer_hardware/network_card + name = "network card" + desc = "A basic wireless network card for usage with standard NTNet frequencies." power_usage = 50 - origin_tech = list("programming" = 2, TECH_ENGINEERING = 1) - critical = 0 - icon_state = "netcard_basic" - hardware_size = 1 + origin_tech = "programming=2;engineering=1" + icon_state = "radio_mini" var/identification_id = null // Identification ID. Technically MAC address of this device. Can't be changed by user. var/identification_string = "" // Identification string, technically nickname seen in the network. Can be set by user. var/long_range = 0 @@ -30,40 +28,13 @@ var/global/ntnet_card_uid = 1 identification_id = ntnet_card_uid ntnet_card_uid++ -/obj/item/weapon/computer_hardware/network_card/advanced - name = "advanced NTNet network card" - desc = "An advanced network card for usage with standard NTNet frequencies. It's transmitter is strong enough to connect even off-station." - long_range = 1 - origin_tech = list("programming" = 4, "engineering" = 2) - power_usage = 100 // Better range but higher power usage. - icon_state = "netcard_advanced" - hardware_size = 1 - -/obj/item/weapon/computer_hardware/network_card/wired - name = "wired NTNet network card" - desc = "An advanced network card for usage with standard NTNet frequencies. This one also supports wired connection." - ethernet = 1 - origin_tech = list("programming" = 5, "engineering" = 3) - power_usage = 100 // Better range but higher power usage. - icon_state = "netcard_ethernet" - hardware_size = 3 - -/obj/item/weapon/computer_hardware/network_card/Destroy() - if(holder2 && (holder2.network_card == src)) - holder2.network_card = null - holder2 = null - ..() - // Returns a string identifier of this network card /obj/item/weapon/computer_hardware/network_card/proc/get_network_tag() return "[identification_string] (NID [identification_id])" // 0 - No signal, 1 - Low signal, 2 - High signal. 3 - Wired Connection /obj/item/weapon/computer_hardware/network_card/proc/get_signal(var/specific_action = 0) - if(!holder2) // Hardware is not installed in anything. No signal. How did this even get called? - return 0 - - if(!enabled) + if(!holder) // Hardware is not installed in anything. No signal. How did this even get called? return 0 if(!check_functionality()) @@ -75,9 +46,9 @@ var/global/ntnet_card_uid = 1 if(!ntnet_global || !ntnet_global.check_function(specific_action)) // NTNet is down and we are not connected via wired connection. No signal. return 0 - if(holder2) + if(holder) - var/turf/T = get_turf(holder2) + var/turf/T = get_turf(holder) if((T && istype(T)) && (T.z == ZLEVEL_STATION || T.z == ZLEVEL_MINING)) // Computer is on station. Low/High signal depending on what type of network card you have if(long_range) @@ -90,17 +61,21 @@ var/global/ntnet_card_uid = 1 return 0 // Computer is not on station and does not have upgraded network card. No signal. -/obj/item/weapon/computer_hardware/network_card/Destroy() - if(holder2 && (holder2.network_card == src)) - holder2.network_card = null - ..() -/obj/item/weapon/computer_hardware/network_card/try_install_component(mob/living/user, obj/item/modular_computer/M, found = 0) - if(!user.drop_item(src)) - return - if(M.network_card) - user << "This computer's network card slot is already occupied by \the [M.network_card]." - return - found = 1 - M.network_card = src - ..(user, M, found) \ No newline at end of file +/obj/item/weapon/computer_hardware/network_card/advanced + name = "advanced network card" + desc = "An advanced network card for usage with standard NTNet frequencies. It's transmitter is strong enough to connect even off-station." + long_range = 1 + origin_tech = "programming=4;engineering=2" + power_usage = 100 // Better range but higher power usage. + icon_state = "radio" + w_class = 1 + +/obj/item/weapon/computer_hardware/network_card/wired + name = "wired network card" + desc = "An advanced network card for usage with standard NTNet frequencies. This one also supports wired connection." + ethernet = 1 + origin_tech = "programming=5;engineering=3" + power_usage = 100 // Better range but higher power usage. + icon_state = "net_wired" + w_class = 3 diff --git a/code/modules/modular_computers/hardware/portable_disk.dm b/code/modules/modular_computers/hardware/portable_disk.dm new file mode 100644 index 00000000000..4878e530150 --- /dev/null +++ b/code/modules/modular_computers/hardware/portable_disk.dm @@ -0,0 +1,27 @@ +/obj/item/weapon/computer_hardware/hard_drive/portable + name = "data disk" + desc = "Removable disk used to store data." + power_usage = 10 + icon_state = "datadisk6" + w_class = 1 + critical = 0 + max_capacity = 16 + origin_tech = "programming=1" + +/obj/item/weapon/computer_hardware/hard_drive/portable/install_default_programs() + return // Empty by default + +/obj/item/weapon/computer_hardware/hard_drive/portable/advanced + name = "advanced data disk" + power_usage = 20 + icon_state = "datadisk5" + max_capacity = 64 + origin_tech = "programming=2" + +/obj/item/weapon/computer_hardware/hard_drive/portable/super + name = "super data disk" + desc = "Removable disk used to store large amounts of data." + power_usage = 40 + icon_state = "datadisk3" + max_capacity = 256 + origin_tech = "programming=4" diff --git a/code/modules/modular_computers/hardware/portable_hard_drive.dm b/code/modules/modular_computers/hardware/portable_hard_drive.dm deleted file mode 100644 index a5eca85594f..00000000000 --- a/code/modules/modular_computers/hardware/portable_hard_drive.dm +++ /dev/null @@ -1,43 +0,0 @@ -// These are basically USB data sticks and may be used to transfer files between devices -/obj/item/weapon/computer_hardware/hard_drive/portable/ - name = "basic data crystal" - desc = "Small crystal with imprinted photonic circuits that can be used to store data. It's capacity is 16 GQ." - power_usage = 10 - icon_state = "flashdrive_basic" - hardware_size = 1 - max_capacity = 16 - origin_tech = list("programming" = 1) - -/obj/item/weapon/computer_hardware/hard_drive/portable/advanced - name = "advanced data crystal" - desc = "Small crystal with imprinted high-density photonic circuits that can be used to store data. It's capacity is 64 GQ." - power_usage = 20 - icon_state = "flashdrive_advanced" - hardware_size = 1 - max_capacity = 64 - origin_tech = list("programming" = 2) - -/obj/item/weapon/computer_hardware/hard_drive/portable/super - name = "super data crystal" - desc = "Small crystal with imprinted ultra-density photonic circuits that can be used to store data. It's capacity is 256 GQ." - power_usage = 40 - icon_state = "flashdrive_super" - hardware_size = 1 - max_capacity = 256 - origin_tech = list("programming" = 4) - -/obj/item/weapon/computer_hardware/hard_drive/portable/New() - ..() - stored_files = list() - recalculate_size() - - -/obj/item/weapon/computer_hardware/hard_drive/portable/try_install_component(mob/living/user, obj/item/modular_computer/M, found = 0) - if(!user.drop_item(src)) - return - if(M.portable_drive) - user << "This computer's portable drive slot is already occupied by \the [M.portable_drive]." - return - found = 1 - M.portable_drive = src - ..(user, M, found) \ No newline at end of file diff --git a/code/modules/modular_computers/hardware/printer.dm b/code/modules/modular_computers/hardware/printer.dm new file mode 100644 index 00000000000..c23905bf119 --- /dev/null +++ b/code/modules/modular_computers/hardware/printer.dm @@ -0,0 +1,62 @@ +/obj/item/weapon/computer_hardware/printer + name = "printer" + desc = "Computer-integrated printer with paper recycling module." + power_usage = 100 + origin_tech = "programming=2;engineering=2" + icon_state = "printer" + w_class = 3 + var/stored_paper = 20 + var/max_paper = 30 + +/obj/item/weapon/computer_hardware/printer/diagnostics(mob/living/user) + ..() + user << "Paper level: [stored_paper]/[max_paper]" + +/obj/item/weapon/computer_hardware/printer/examine(mob/user) + ..() + user << "Paper level: [stored_paper]/[max_paper]" + + +/obj/item/weapon/computer_hardware/printer/proc/print_text(var/text_to_print, var/paper_title = "") + if(!stored_paper) + return FALSE + if(!check_functionality()) + return FALSE + + var/obj/item/weapon/paper/P = new/obj/item/weapon/paper(get_turf(holder)) + + // 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() + stored_paper-- + P = null + return TRUE + +/obj/item/weapon/computer_hardware/printer/try_insert(obj/item/I, mob/living/user = null) + if(istype(I, /obj/item/weapon/paper)) + if(user && !user.unEquip(I)) + return FALSE + + if(stored_paper >= max_paper) + user << "You try to add \the [I] into [src], but it's paper bin is full!" + return FALSE + + user << "You insert \the [I] into [src]'s paper recycler." + qdel(I) + stored_paper++ + return TRUE + return FALSE + +/obj/item/weapon/computer_hardware/printer/mini + name = "miniprinter" + desc = "A small printer with paper recycling module." + power_usage = 50 + icon_state = "printer_mini" + w_class = 1 + stored_paper = 5 + max_paper = 15 \ No newline at end of file diff --git a/code/modules/modular_computers/hardware/processor_unit.dm b/code/modules/modular_computers/hardware/processor_unit.dm deleted file mode 100644 index 2592d239975..00000000000 --- a/code/modules/modular_computers/hardware/processor_unit.dm +++ /dev/null @@ -1,51 +0,0 @@ -// CPU that allows the computer to run programs. -// Better CPUs are obtainable via research and can run more programs on background. - -/obj/item/weapon/computer_hardware/processor_unit - name = "standard processor" - desc = "A standard CPU used in most computers. It can run up to three programs simultaneously." - icon_state = "cpu_normal" - hardware_size = 2 - power_usage = 50 - critical = 1 - malfunction_probability = 1 - origin_tech = list("programming" = 3, "engineering" = 2) - - var/max_idle_programs = 2 // 2 idle, + 1 active = 3 as said in description. - -/obj/item/weapon/computer_hardware/processor_unit/small - name = "standard microprocessor" - desc = "A standard miniaturised CPU used in portable devices. It can run up to two programs simultaneously." - icon_state = "cpu_small" - hardware_size = 1 - power_usage = 25 - max_idle_programs = 1 - origin_tech = list("programming" = 2, "engineering" = 2) - -/obj/item/weapon/computer_hardware/processor_unit/photonic - name = "photonic processor" - desc = "An advanced experimental CPU that uses photonic core instead of regular circuitry. It can run up to five programs simultaneously, but uses a lot of power." - icon_state = "cpu_normal_photonic" - hardware_size = 2 - power_usage = 250 - max_idle_programs = 4 - origin_tech = list("programming" = 5, "engineering" = 4) - -/obj/item/weapon/computer_hardware/processor_unit/photonic/small - name = "photonic microprocessor" - desc = "An advanced miniaturised CPU for use in portable devices. It uses photonic core instead of regular circuitry. It can run up to three programs simultaneously." - icon_state = "cpu_small_photonic" - hardware_size = 1 - power_usage = 75 - max_idle_programs = 2 - origin_tech = list("programming" = 4, "engineering" = 3) - -/obj/item/weapon/computer_hardware/processor_unit/try_install_component(mob/living/user, obj/item/modular_computer/M, found = 0) - if(!user.drop_item(src)) - return - if(M.processor_unit) - user << "This computer's processor slot is already occupied by \the [M.processor_unit]." - return - found = 1 - M.processor_unit = src - ..(user, M, found) \ No newline at end of file diff --git a/code/modules/modular_computers/hardware/recharger.dm b/code/modules/modular_computers/hardware/recharger.dm new file mode 100644 index 00000000000..fc3469fd3aa --- /dev/null +++ b/code/modules/modular_computers/hardware/recharger.dm @@ -0,0 +1,91 @@ +/obj/item/weapon/computer_hardware/recharger + critical = 1 + enabled = 1 + var/charge_rate = 100 + +/obj/item/weapon/computer_hardware/recharger/proc/use_power(amount, charging=0) + if(charging) + return 1 + return 0 + +/obj/item/weapon/computer_hardware/recharger/process() + ..() + if(!holder || !holder.battery_module || !holder.battery_module.battery) + return + + var/obj/item/weapon/stock_parts/cell/cell = holder.battery_module.battery + if(cell.charge >= cell.maxcharge) + return + + if(use_power(charge_rate, charging=1)) + holder.give_power(charge_rate * CELLRATE) + + +/obj/item/weapon/computer_hardware/recharger/APC + name = "area power connector" + desc = "A device that wirelessly recharges connected device from nearby APC." + icon_state = "charger_APC" + w_class = 2 // Can't be installed into tablets/PDAs + origin_tech = "programming=2;engineering=2;powerstorage=3" + +/obj/item/weapon/computer_hardware/recharger/APC/use_power(amount, charging=0) + if(istype(holder.physical, /obj/machinery)) + var/obj/machinery/M = holder.physical + if(M.powered()) + M.use_power(amount) + return 1 + + else + var/area/A = get_area(src) + if(!A || !isarea(A) || !A.master) + return 0 + + if(A.master.powered(EQUIP)) + A.master.use_power(amount, EQUIP) + return 1 + return 0 + +/obj/item/weapon/computer_hardware/recharger/wired + name = "wired power connector" + desc = "A power connector that recharges connected device from nearby power wire. Incompatible with portable computers." + icon_state = "charger_wire" + w_class = 3 + origin_tech = "engineering=2;powerstorage=1" + +/obj/item/weapon/computer_hardware/recharger/wired/can_install(obj/item/device/modular_computer/M, mob/living/user = null) + if(istype(M.physical, /obj/machinery) && M.physical.anchored) + return ..() + user << "\The [src] is incompatible with portable computers!" + return 0 + +/obj/item/weapon/computer_hardware/recharger/wired/use_power(amount, charging=0) + if(istype(holder.physical, /obj/machinery) && holder.physical.anchored) + var/obj/machinery/M = holder.physical + var/turf/T = M.loc + if(!T || !istype(T)) + return 0 + + var/obj/structure/cable/C = T.get_cable_node() + if(!C || !C.powernet) + return 0 + + var/power_in_net = C.powernet.avail-C.powernet.load + + if(power_in_net && power_in_net > amount) + C.powernet.load += amount + return 1 + + return 0 + + + +// This is not intended to be obtainable in-game. Intended for adminbus and debugging purposes. +/obj/item/weapon/computer_hardware/recharger/lambda + name = "lambda coil" + desc = "A very complex device that draws power from it's own bluespace dimension." + icon_state = "charger_lambda" + w_class = 1 + charge_rate = 100000 + +/obj/item/weapon/computer_hardware/recharger/lambda/use_power(amount, charging=0) + return 1 diff --git a/code/modules/modular_computers/hardware/tesla_link.dm b/code/modules/modular_computers/hardware/tesla_link.dm deleted file mode 100644 index 662cab79541..00000000000 --- a/code/modules/modular_computers/hardware/tesla_link.dm +++ /dev/null @@ -1,33 +0,0 @@ -/obj/item/weapon/computer_hardware/tesla_link - name = "tesla link" - desc = "An advanced tesla link that wirelessly recharges connected device from nearby area power controller." - critical = 0 - enabled = 1 - icon_state = "teslalink" - hardware_size = 2 // Can't be installed into tablets - origin_tech = list("programming" = 2, "powerstorage" = 3, "engineering" = 2) - var/obj/machinery/modular_computer/holder - -/obj/item/weapon/computer_hardware/tesla_link/New(var/obj/L) - if(istype(L, /obj/machinery/modular_computer)) - holder = L - return - ..(L) - -/obj/item/weapon/computer_hardware/tesla_link/Destroy() - if(holder && (holder.tesla_link == src)) - holder.tesla_link = null - ..() - -/obj/item/weapon/computer_hardware/tesla_link/try_install_component(mob/living/user, obj/item/modular_computer/M, found = 0) - if(!user.drop_item(src)) - return - if(istype(M, /obj/item/modular_computer/processor)) - var/obj/item/modular_computer/processor/P = M - if(P.machinery_computer.tesla_link) - user << "This computer's tesla link slot is already occupied by \the [P.machinery_computer.tesla_link]." - return - holder = P.machinery_computer - P.machinery_computer.tesla_link = src - found = 1 - ..(user, M, found) \ No newline at end of file diff --git a/code/modules/modular_computers/laptop_vendor.dm b/code/modules/modular_computers/laptop_vendor.dm index a6f0b5bbb54..c090d752aa2 100644 --- a/code/modules/modular_computers/laptop_vendor.dm +++ b/code/modules/modular_computers/laptop_vendor.dm @@ -10,8 +10,8 @@ density = 1 // The actual laptop/tablet - var/obj/machinery/modular_computer/laptop/fabricated_laptop = null - var/obj/item/modular_computer/tablet/fabricated_tablet = null + var/obj/item/device/modular_computer/laptop/fabricated_laptop = null + var/obj/item/device/modular_computer/tablet/fabricated_tablet = null // Utility vars var/state = 0 // 0: Select device type, 1: Select loadout, 2: Payment, 3: Thankyou screen @@ -24,8 +24,8 @@ var/dev_battery = 1 // 1: Default, 2: Upgraded, 3: Advanced var/dev_disk = 1 // 1: Default, 2: Upgraded, 3: Advanced var/dev_netcard = 0 // 0: None, 1: Basic, 2: Long-Range - var/dev_tesla = 0 // 0: None, 1: Standard (LAPTOP ONLY) - var/dev_nanoprint = 0 // 0: None, 1: Standard + var/dev_apc_recharger = 0 // 0: None, 1: Standard (LAPTOP ONLY) + var/dev_printer = 0 // 0: None, 1: Standard var/dev_card = 0 // 0: None, 1: Standard // Removes all traces of old order and allows you to begin configuration from scratch. @@ -42,8 +42,8 @@ dev_battery = 1 dev_disk = 1 dev_netcard = 0 - dev_tesla = 0 - dev_nanoprint = 0 + dev_apc_recharger = 0 + dev_printer = 0 dev_card = 0 // Recalculates the price and optionally even fabricates the device. @@ -51,109 +51,111 @@ total_price = 0 if(devtype == 1) // Laptop, generally cheaper to make it accessible for most station roles if(fabricate) - fabricated_laptop = new(src) + fabricated_laptop = new /obj/item/device/modular_computer/laptop/buildable(src) + fabricated_laptop.install_component(new /obj/item/weapon/computer_hardware/battery) total_price = 99 switch(dev_cpu) if(1) if(fabricate) - fabricated_laptop.cpu.processor_unit = new/obj/item/weapon/computer_hardware/processor_unit/small(fabricated_laptop.cpu) + fabricated_laptop.install_component(new /obj/item/weapon/computer_hardware/processor_unit/small) if(2) if(fabricate) - fabricated_laptop.cpu.processor_unit = new/obj/item/weapon/computer_hardware/processor_unit(fabricated_laptop.cpu) + fabricated_laptop.install_component(new /obj/item/weapon/computer_hardware/processor_unit) total_price += 299 switch(dev_battery) if(1) // Basic(750C) if(fabricate) - fabricated_laptop.cpu.battery_module = new/obj/item/weapon/computer_hardware/battery_module(fabricated_laptop.cpu) + fabricated_laptop.battery_module.try_insert(new /obj/item/weapon/stock_parts/cell/computer) if(2) // Upgraded(1100C) if(fabricate) - fabricated_laptop.cpu.battery_module = new/obj/item/weapon/computer_hardware/battery_module/advanced(fabricated_laptop.cpu) + fabricated_laptop.battery_module.try_insert(new /obj/item/weapon/stock_parts/cell/computer/advanced) total_price += 199 if(3) // Advanced(1500C) if(fabricate) - fabricated_laptop.cpu.battery_module = new/obj/item/weapon/computer_hardware/battery_module/super(fabricated_laptop.cpu) + fabricated_laptop.battery_module.try_insert(new /obj/item/weapon/stock_parts/cell/computer/super) total_price += 499 switch(dev_disk) if(1) // Basic(128GQ) if(fabricate) - fabricated_laptop.cpu.hard_drive = new/obj/item/weapon/computer_hardware/hard_drive(fabricated_laptop.cpu) + fabricated_laptop.install_component(new /obj/item/weapon/computer_hardware/hard_drive) if(2) // Upgraded(256GQ) if(fabricate) - fabricated_laptop.cpu.hard_drive = new/obj/item/weapon/computer_hardware/hard_drive/advanced(fabricated_laptop.cpu) + fabricated_laptop.install_component(new /obj/item/weapon/computer_hardware/hard_drive/advanced) total_price += 99 if(3) // Advanced(512GQ) if(fabricate) - fabricated_laptop.cpu.hard_drive = new/obj/item/weapon/computer_hardware/hard_drive/super(fabricated_laptop.cpu) + fabricated_laptop.install_component(new /obj/item/weapon/computer_hardware/hard_drive/super) total_price += 299 switch(dev_netcard) if(1) // Basic(Short-Range) if(fabricate) - fabricated_laptop.cpu.network_card = new/obj/item/weapon/computer_hardware/network_card(fabricated_laptop.cpu) + fabricated_laptop.install_component(new /obj/item/weapon/computer_hardware/network_card) total_price += 99 if(2) // Advanced (Long Range) if(fabricate) - fabricated_laptop.cpu.network_card = new/obj/item/weapon/computer_hardware/network_card/advanced(fabricated_laptop.cpu) + fabricated_laptop.install_component(new /obj/item/weapon/computer_hardware/network_card/advanced) total_price += 299 - if(dev_tesla) + if(dev_apc_recharger) total_price += 399 if(fabricate) - fabricated_laptop.tesla_link = new/obj/item/weapon/computer_hardware/tesla_link(fabricated_laptop) - if(dev_nanoprint) + fabricated_laptop.install_component(new /obj/item/weapon/computer_hardware/recharger/APC) + if(dev_printer) total_price += 99 if(fabricate) - fabricated_laptop.cpu.nano_printer = new/obj/item/weapon/computer_hardware/nano_printer(fabricated_laptop.cpu) + fabricated_laptop.install_component(new /obj/item/weapon/computer_hardware/printer/mini) if(dev_card) total_price += 199 if(fabricate) - fabricated_laptop.cpu.card_slot = new/obj/item/weapon/computer_hardware/card_slot(fabricated_laptop.cpu) + fabricated_laptop.install_component(new /obj/item/weapon/computer_hardware/card_slot) return total_price else if(devtype == 2) // Tablet, more expensive, not everyone could probably afford this. if(fabricate) fabricated_tablet = new(src) - fabricated_tablet.processor_unit = new/obj/item/weapon/computer_hardware/processor_unit/small(fabricated_tablet) + fabricated_tablet.install_component(new /obj/item/weapon/computer_hardware/battery) + fabricated_tablet.install_component(new /obj/item/weapon/computer_hardware/processor_unit/small) total_price = 199 switch(dev_battery) if(1) // Basic(300C) if(fabricate) - fabricated_tablet.battery_module = new/obj/item/weapon/computer_hardware/battery_module/nano(fabricated_tablet) + fabricated_tablet.battery_module.try_insert(new /obj/item/weapon/stock_parts/cell/computer/nano) if(2) // Upgraded(500C) if(fabricate) - fabricated_tablet.battery_module = new/obj/item/weapon/computer_hardware/battery_module/micro(fabricated_tablet) + fabricated_tablet.battery_module.try_insert(new /obj/item/weapon/stock_parts/cell/computer/micro) total_price += 199 if(3) // Advanced(750C) if(fabricate) - fabricated_tablet.battery_module = new/obj/item/weapon/computer_hardware/battery_module(fabricated_tablet) + fabricated_tablet.battery_module.try_insert(new /obj/item/weapon/stock_parts/cell/computer) total_price += 499 switch(dev_disk) if(1) // Basic(32GQ) if(fabricate) - fabricated_tablet.hard_drive = new/obj/item/weapon/computer_hardware/hard_drive/micro(fabricated_tablet) + fabricated_tablet.install_component(new /obj/item/weapon/computer_hardware/hard_drive/micro) if(2) // Upgraded(64GQ) if(fabricate) - fabricated_tablet.hard_drive = new/obj/item/weapon/computer_hardware/hard_drive/small(fabricated_tablet) + fabricated_tablet.install_component(new /obj/item/weapon/computer_hardware/hard_drive/small) total_price += 99 if(3) // Advanced(128GQ) if(fabricate) - fabricated_tablet.hard_drive = new/obj/item/weapon/computer_hardware/hard_drive(fabricated_tablet) + fabricated_tablet.install_component(new /obj/item/weapon/computer_hardware/hard_drive) total_price += 299 switch(dev_netcard) if(1) // Basic(Short-Range) if(fabricate) - fabricated_tablet.network_card = new/obj/item/weapon/computer_hardware/network_card(fabricated_tablet) + fabricated_tablet.install_component(new/obj/item/weapon/computer_hardware/network_card) total_price += 99 if(2) // Advanced (Long Range) if(fabricate) - fabricated_tablet.network_card = new/obj/item/weapon/computer_hardware/network_card/advanced(fabricated_tablet) + fabricated_tablet.install_component(new/obj/item/weapon/computer_hardware/network_card/advanced) total_price += 299 - if(dev_nanoprint) + if(dev_printer) total_price += 99 if(fabricate) - fabricated_tablet.nano_printer = new/obj/item/weapon/computer_hardware/nano_printer(fabricated_tablet) + fabricated_tablet.install_component(new/obj/item/weapon/computer_hardware/printer) if(dev_card) total_price += 199 if(fabricate) - fabricated_tablet.card_slot = new/obj/item/weapon/computer_hardware/card_slot(fabricated_tablet) + fabricated_tablet.install_component(new/obj/item/weapon/computer_hardware/card_slot) return total_price return 0 @@ -200,11 +202,11 @@ fabricate_and_recalc_price(0) return 1 if("hw_tesla") - dev_tesla = text2num(params["tesla"]) + dev_apc_recharger = text2num(params["tesla"]) fabricate_and_recalc_price(0) return 1 if("hw_nanoprint") - dev_nanoprint = text2num(params["print"]) + dev_printer = text2num(params["print"]) fabricate_and_recalc_price(0) return 1 if("hw_card") @@ -232,7 +234,6 @@ obj/machinery/lapvend/attackby(obj/item/I as obj, mob/user as mob) - if(istype(I,/obj/item/stack/spacecash)) var/obj/item/stack/spacecash/c = I @@ -249,12 +250,9 @@ obj/machinery/lapvend/attackby(obj/item/I as obj, mob/user as mob) if(process_payment(D,I)) fabricate_and_recalc_price(1) if((devtype == 1) && fabricated_laptop) - fabricated_laptop.cpu.battery_module.charge_to_full() fabricated_laptop.forceMove(src.loc) - fabricated_laptop.close_laptop() fabricated_laptop = null else if((devtype == 2) && fabricated_tablet) - fabricated_tablet.battery_module.charge_to_full() fabricated_tablet.forceMove(src.loc) fabricated_tablet = null say("Enjoy your new product!") @@ -283,8 +281,8 @@ obj/machinery/lapvend/attackby(obj/item/I as obj, mob/user as mob) data["hw_battery"] = dev_battery data["hw_disk"] = dev_disk data["hw_netcard"] = dev_netcard - data["hw_tesla"] = dev_tesla - data["hw_nanoprint"] = dev_nanoprint + data["hw_tesla"] = dev_apc_recharger + data["hw_nanoprint"] = dev_printer data["hw_card"] = dev_card data["hw_cpu"] = dev_cpu if(state == 1 || state == 2) diff --git a/code/modules/research/designs/autolathe_designs.dm b/code/modules/research/designs/autolathe_designs.dm index 565ec192dfb..5ccea90968e 100644 --- a/code/modules/research/designs/autolathe_designs.dm +++ b/code/modules/research/designs/autolathe_designs.dm @@ -732,14 +732,14 @@ name = "Laptop Frame" id = "laptop" build_type = AUTOLATHE - materials = list(MAT_METAL = 1200, MAT_GLASS = 200) - build_path = /obj/machinery/modular_computer/laptop/buildable + materials = list(MAT_METAL = 10000, MAT_GLASS = 1000) + build_path = /obj/item/device/modular_computer/laptop/buildable category = list("initial","Misc") /datum/design/tablet name = "Tablet Frame" id = "tablet" build_type = AUTOLATHE - materials = list(MAT_METAL = 500, MAT_GLASS = 1000) - build_path = /obj/item/modular_computer/tablet - category = list("initial","Misc") \ No newline at end of file + materials = list(MAT_METAL = 2000, MAT_GLASS = 1000) + build_path = /obj/item/device/modular_computer/tablet + category = list("initial","Misc") diff --git a/code/modules/research/designs/computer_part_designs.dm b/code/modules/research/designs/computer_part_designs.dm index ae91050960e..dc6c69ad461 100644 --- a/code/modules/research/designs/computer_part_designs.dm +++ b/code/modules/research/designs/computer_part_designs.dm @@ -3,16 +3,16 @@ //////////////////////////////////////// /datum/design/disk/normal - name = "basic hard drive" + name = "hard disk drive" id = "hdd_basic" req_tech = list("programming" = 1, "engineering" = 1) build_type = PROTOLATHE materials = list(MAT_METAL = 400, MAT_GLASS = 100) - build_path = /obj/item/weapon/computer_hardware/hard_drive/ + build_path = /obj/item/weapon/computer_hardware/hard_drive category = list("Computer Parts") /datum/design/disk/advanced - name = "advanced hard drive" + name = "advanced hard disk drive" id = "hdd_advanced" req_tech = list("programming" = 2, "engineering" = 2) build_type = PROTOLATHE @@ -21,7 +21,7 @@ category = list("Computer Parts") /datum/design/disk/super - name = "super hard drive" + name = "super hard disk drive" id = "hdd_super" req_tech = list("programming" = 3, "engineering" = 3) build_type = PROTOLATHE @@ -30,7 +30,7 @@ category = list("Computer Parts") /datum/design/disk/cluster - name = "cluster hard drive" + name = "cluster hard disk drive" id = "hdd_cluster" req_tech = list("programming" = 4, "engineering" = 4) build_type = PROTOLATHE @@ -39,8 +39,8 @@ category = list("Computer Parts") /datum/design/disk/small - name = "small hard drive" - id = "hdd_small" + name = "solid state drive" + id = "ssd_small" req_tech = list("programming" = 2, "engineering" = 2) build_type = PROTOLATHE materials = list(MAT_METAL = 800, MAT_GLASS = 200) @@ -48,17 +48,18 @@ category = list("Computer Parts") /datum/design/disk/micro - name = "micro hard drive" - id = "hdd_micro" + name = "micro solid state drive" + id = "ssd_micro" req_tech = list("programming" = 1, "engineering" = 1) build_type = PROTOLATHE materials = list(MAT_METAL = 400, MAT_GLASS = 100) build_path = /obj/item/weapon/computer_hardware/hard_drive/micro category = list("Computer Parts") + // Network cards /datum/design/netcard/basic - name = "basic network card" + name = "network card" id = "netcard_basic" req_tech = list("programming" = 2, "engineering" = 1) build_type = IMPRINTER @@ -87,9 +88,10 @@ build_path = /obj/item/weapon/computer_hardware/network_card/wired category = list("Computer Parts") -// Data crystals (USB flash drives) + +// Data disks /datum/design/portabledrive/basic - name = "basic data crystal" + name = "data disk" id = "portadrive_basic" req_tech = list("programming" = 1) build_type = IMPRINTER @@ -99,7 +101,7 @@ category = list("Computer Parts") /datum/design/portabledrive/advanced - name = "advanced data crystal" + name = "advanced data disk" id = "portadrive_advanced" req_tech = list("programming" = 2) build_type = IMPRINTER @@ -109,7 +111,7 @@ category = list("Computer Parts") /datum/design/portabledrive/super - name = "super data crystal" + name = "super data disk" id = "portadrive_super" req_tech = list("programming" = 4) build_type = IMPRINTER @@ -118,9 +120,10 @@ build_path = /obj/item/weapon/computer_hardware/hard_drive/portable/super category = list("Computer Parts") + // Card slot /datum/design/cardslot - name = "RFID card slot" + name = "ID card slot" id = "cardslot" req_tech = list("programming" = 2) build_type = PROTOLATHE @@ -128,34 +131,45 @@ build_path = /obj/item/weapon/computer_hardware/card_slot category = list("Computer Parts") -// Nano printer -/datum/design/nanoprinter - name = "nano printer" - id = "nanoprinter" +// Mini printer +/datum/design/miniprinter + name = "miniprinter" + id = "miniprinter" req_tech = list("programming" = 2, "engineering" = 2) build_type = PROTOLATHE materials = list(MAT_METAL = 600) - build_path = /obj/item/weapon/computer_hardware/nano_printer + build_path = /obj/item/weapon/computer_hardware/printer/mini category = list("Computer Parts") -// Tesla Link -/datum/design/teslalink - name = "tesla link" - id = "teslalink" + +// APC Link +/datum/design/APClink + name = "area power connector" + id = "APClink" req_tech = list("programming" = 2, "powerstorage" = 3, "engineering" = 2) build_type = PROTOLATHE materials = list(MAT_METAL = 2000) - build_path = /obj/item/weapon/computer_hardware/tesla_link + build_path = /obj/item/weapon/computer_hardware/recharger/APC category = list("Computer Parts") + // Batteries +/datum/design/battery/controller + name = "power cell controller" + id = "bat_control" + req_tech = list("powerstorage" = 1, "engineering" = 1) + build_type = PROTOLATHE + materials = list(MAT_METAL = 400) + build_path = /obj/item/weapon/computer_hardware/battery + category = list("Computer Parts") + /datum/design/battery/normal - name = "standard battery module" + name = "battery module" id = "bat_normal" req_tech = list("powerstorage" = 1, "engineering" = 1) build_type = PROTOLATHE materials = list(MAT_METAL = 400) - build_path = /obj/item/weapon/computer_hardware/battery_module + build_path = /obj/item/weapon/stock_parts/cell/computer category = list("Computer Parts") /datum/design/battery/advanced @@ -164,7 +178,7 @@ req_tech = list("powerstorage" = 2, "engineering" = 2) build_type = PROTOLATHE materials = list(MAT_METAL = 800) - build_path = /obj/item/weapon/computer_hardware/battery_module/advanced + build_path = /obj/item/weapon/stock_parts/cell/computer/advanced category = list("Computer Parts") /datum/design/battery/super @@ -173,16 +187,7 @@ req_tech = list("powerstorage" = 3, "engineering" = 3) build_type = PROTOLATHE materials = list(MAT_METAL = 1600) - build_path = /obj/item/weapon/computer_hardware/battery_module/super - category = list("Computer Parts") - -/datum/design/battery/ultra - name = "ultra battery module" - id = "bat_ultra" - req_tech = list("powerstorage" = 5, "engineering" = 4) - build_type = PROTOLATHE - materials = list(MAT_METAL = 3200) - build_path = /obj/item/weapon/computer_hardware/battery_module/ultra + build_path = /obj/item/weapon/stock_parts/cell/computer/super category = list("Computer Parts") /datum/design/battery/nano @@ -191,7 +196,7 @@ req_tech = list("powerstorage" = 1, "engineering" = 1) build_type = PROTOLATHE materials = list(MAT_METAL = 200) - build_path = /obj/item/weapon/computer_hardware/battery_module/nano + build_path = /obj/item/weapon/stock_parts/cell/computer/nano category = list("Computer Parts") /datum/design/battery/micro @@ -200,12 +205,13 @@ req_tech = list("powerstorage" = 2, "engineering" = 2) build_type = PROTOLATHE materials = list(MAT_METAL = 400) - build_path = /obj/item/weapon/computer_hardware/battery_module/micro + build_path = /obj/item/weapon/stock_parts/cell/computer/micro category = list("Computer Parts") + // Processor unit /datum/design/cpu - name = "computer processor unit" + name = "processor board" id = "cpu_normal" req_tech = list("programming" = 3, "engineering" = 2) build_type = IMPRINTER @@ -215,7 +221,7 @@ category = list("Computer Parts") /datum/design/cpu/small - name = "computer microprocessor unit" + name = "microprocessor" id = "cpu_small" req_tech = list("programming" = 2, "engineering" = 2) build_type = IMPRINTER @@ -225,7 +231,7 @@ category = list("Computer Parts") /datum/design/cpu/photonic - name = "computer photonic processor unit" + name = "photonic processor board" id = "pcpu_normal" req_tech = list("programming" = 5, "engineering" = 4) build_type = IMPRINTER @@ -235,7 +241,7 @@ category = list("Computer Parts") /datum/design/cpu/photonic/small - name = "computer photonic microprocessor unit" + name = "photonic microprocessor" id = "pcpu_small" req_tech = list("programming" = 4, "engineering" = 3) build_type = IMPRINTER diff --git a/icons/obj/machines/research.dmi b/icons/obj/machines/research.dmi index 741f770f686..c694d6789f6 100644 Binary files a/icons/obj/machines/research.dmi and b/icons/obj/machines/research.dmi differ diff --git a/icons/obj/modular_components.dmi b/icons/obj/modular_components.dmi deleted file mode 100644 index 3594a12c17f..00000000000 Binary files a/icons/obj/modular_components.dmi and /dev/null differ diff --git a/icons/obj/modular_console.dmi b/icons/obj/modular_console.dmi index a157462f57a..85d6026617f 100644 Binary files a/icons/obj/modular_console.dmi and b/icons/obj/modular_console.dmi differ diff --git a/icons/obj/modular_laptop.dmi b/icons/obj/modular_laptop.dmi index b3e0cb53648..2daeee0c7a4 100644 Binary files a/icons/obj/modular_laptop.dmi and b/icons/obj/modular_laptop.dmi differ diff --git a/icons/obj/modular_tablet.dmi b/icons/obj/modular_tablet.dmi index 1872315f49f..82f4e1438f6 100644 Binary files a/icons/obj/modular_tablet.dmi and b/icons/obj/modular_tablet.dmi differ diff --git a/icons/obj/module.dmi b/icons/obj/module.dmi index 872ed24c8a3..5af3a037b2a 100644 Binary files a/icons/obj/module.dmi and b/icons/obj/module.dmi differ diff --git a/tgstation.dme b/tgstation.dme index 47985766759..17293fa14c5 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -1519,14 +1519,18 @@ #include "code\modules\mob\new_player\preferences_setup.dm" #include "code\modules\mob\new_player\sprite_accessories.dm" #include "code\modules\modular_computers\laptop_vendor.dm" -#include "code\modules\modular_computers\computers\item\modular_computer.dm" +#include "code\modules\modular_computers\computers\item\computer.dm" +#include "code\modules\modular_computers\computers\item\computer_components.dm" +#include "code\modules\modular_computers\computers\item\computer_damage.dm" +#include "code\modules\modular_computers\computers\item\computer_power.dm" +#include "code\modules\modular_computers\computers\item\computer_ui.dm" +#include "code\modules\modular_computers\computers\item\laptop.dm" #include "code\modules\modular_computers\computers\item\processor.dm" #include "code\modules\modular_computers\computers\item\tablet.dm" #include "code\modules\modular_computers\computers\item\tablet_presets.dm" #include "code\modules\modular_computers\computers\machinery\console_presets.dm" #include "code\modules\modular_computers\computers\machinery\modular_computer.dm" #include "code\modules\modular_computers\computers\machinery\modular_console.dm" -#include "code\modules\modular_computers\computers\machinery\modular_laptop.dm" #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" @@ -1542,15 +1546,15 @@ #include "code\modules\modular_computers\file_system\programs\powermonitor.dm" #include "code\modules\modular_computers\file_system\programs\antagonist\dos.dm" #include "code\modules\modular_computers\file_system\programs\antagonist\revelation.dm" +#include "code\modules\modular_computers\hardware\_hardware.dm" #include "code\modules\modular_computers\hardware\battery_module.dm" #include "code\modules\modular_computers\hardware\card_slot.dm" +#include "code\modules\modular_computers\hardware\CPU.dm" #include "code\modules\modular_computers\hardware\hard_drive.dm" -#include "code\modules\modular_computers\hardware\hardware.dm" -#include "code\modules\modular_computers\hardware\nano_printer.dm" #include "code\modules\modular_computers\hardware\network_card.dm" -#include "code\modules\modular_computers\hardware\portable_hard_drive.dm" -#include "code\modules\modular_computers\hardware\processor_unit.dm" -#include "code\modules\modular_computers\hardware\tesla_link.dm" +#include "code\modules\modular_computers\hardware\portable_disk.dm" +#include "code\modules\modular_computers\hardware\printer.dm" +#include "code\modules\modular_computers\hardware\recharger.dm" #include "code\modules\modular_computers\NTNet\NTNet.dm" #include "code\modules\modular_computers\NTNet\NTNet_relay.dm" #include "code\modules\modular_computers\NTNet\NTNRC\conversation.dm"