Removes AI and Charge parts from tablets, adds support for more later. (#70012)

* Removes recharger tablet parts

Removes 'advanced' tablet subtypes that we used before PDAs were added, in some jobs.
Replaces Roboticist's advanced tablet mail with a laptop
Moves the notepad's note var from the tablet, to the note app
Moves modular computer's defines into their own file

Machine computers now directly use power from the machine they're in, while the rest uses power cells.
Silicon tablets don't use power at all.

Co-authored-by: san7890 <the@san7890.com>
Co-authored-by: Mothblocks <35135081+Mothblocks@users.noreply.github.com>
This commit is contained in:
John Willard
2022-09-22 20:58:20 -07:00
committed by GitHub
co-authored by san7890 Mothblocks
parent c7f5bc49da
commit ca229574f6
46 changed files with 307 additions and 718 deletions
@@ -1,68 +0,0 @@
/obj/proc/is_modular_computer()
return FALSE
//item
/obj/item/modular_computer/is_modular_computer()
return TRUE
//machine
/obj/machinery/modular_computer/is_modular_computer()
return TRUE
/obj/proc/get_modular_computer_part(part_type)
return null
//item
/obj/item/modular_computer/get_modular_computer_part(part_type)
if(!part_type)
stack_trace("get_modular_computer_part() called without a valid part_type")
return null
return all_components[part_type]
//machine
/obj/machinery/modular_computer/get_modular_computer_part(part_type)
if(!part_type)
stack_trace("get_modular_computer_part() called without a valid part_type")
return null
return cpu?.all_components[part_type]
/obj/proc/get_modular_computer_parts_examine(mob/user)
. = list()
if(!is_modular_computer())
return
var/user_is_adjacent = Adjacent(user) //don't reveal full details unless they're close enough to see it on the screen anyway.
var/obj/item/computer_hardware/ai_slot/ai_slot = get_modular_computer_part(MC_AI)
if(ai_slot)
if(ai_slot.stored_card)
if(user_is_adjacent)
. += "It has a slot installed for an intelliCard which contains: [ai_slot.stored_card.name]"
else
. += "It has a slot installed for an intelliCard, which appears to be occupied."
. += span_info("Alt-click to eject the intelliCard.")
else
. += "It has a slot installed for an intelliCard."
var/obj/item/computer_hardware/card_slot/card_slot = get_modular_computer_part(MC_CARD)
var/obj/item/computer_hardware/card_slot/card_slot2 = get_modular_computer_part(MC_CARD2)
var/multiple_slots = istype(card_slot) && istype(card_slot2)
if(card_slot)
if(card_slot?.stored_card || card_slot2?.stored_card)
var/obj/item/card/id/first_ID = card_slot?.stored_card
var/obj/item/card/id/second_ID = card_slot2?.stored_card
var/multiple_cards = istype(first_ID) && istype(second_ID)
if(user_is_adjacent)
. += "It has [multiple_slots ? "two slots" : "a slot"] for identification cards installed[multiple_cards ? " which contain [first_ID] and [second_ID]" : ", one of which contains [first_ID ? first_ID : second_ID]"]."
else
. += "It has [multiple_slots ? "two slots" : "a slot"] for identification cards installed, [multiple_cards ? "both of which appear" : "and one of them appears"] to be occupied."
. += span_info("Alt-click [src] to eject the identification card[multiple_cards ? "s":""].")
else
. += "It has [multiple_slots ? "two slots" : "a slot"] installed for identification cards."
var/obj/item/computer_hardware/printer/printer_slot = get_modular_computer_part(MC_PRINT)
if(printer_slot)
. += "It has a printer installed."
if(user_is_adjacent)
. += "The printer's paper levels are at: [printer_slot.stored_paper]/[printer_slot.max_paper].</span>"
@@ -295,7 +295,33 @@ GLOBAL_LIST_EMPTY(TabletMessengers) // a list of all active messengers, similar
else if(atom_integrity < max_integrity)
. += span_warning("It is damaged.")
. += get_modular_computer_parts_examine(user)
var/obj/item/computer_hardware/hard_drive/hdd = all_components[MC_HDD]
for(var/datum/computer_file/app_examine as anything in hdd.stored_files)
if(app_examine.on_examine(src, user))
. += app_examine.on_examine(src, user)
var/obj/item/computer_hardware/card_slot/card_slot = all_components[MC_CARD]
var/obj/item/computer_hardware/card_slot/card_slot2 = all_components[MC_CARD2]
var/multiple_slots = istype(card_slot) && istype(card_slot2)
if(card_slot)
if(card_slot.stored_card || card_slot2?.stored_card)
var/obj/item/card/id/first_ID = card_slot?.stored_card
var/obj/item/card/id/second_ID = card_slot2?.stored_card
var/multiple_cards = (first_ID && second_ID)
if(Adjacent(user))
. += "It has [multiple_slots ? "two slots" : "a slot"] for identification cards installed[multiple_cards ? " which contain [first_ID] and [second_ID]" : ", one of which contains [first_ID || second_ID]"]."
else
. += "It has [multiple_slots ? "two slots" : "a slot"] for identification cards installed, [multiple_cards ? "both of which appear" : "and one of them appears"] to be occupied."
. += span_info("Alt-click [src] to eject the identification card[multiple_cards ? "s":""].")
else
. += "It has [multiple_slots ? "two slots" : "a slot"] installed for identification cards."
var/obj/item/computer_hardware/printer/printer_slot = all_components[MC_PRINT]
if(printer_slot)
. += "It has a printer installed."
if(Adjacent(user))
. += "The printer's paper levels are at: [printer_slot.stored_paper]/[printer_slot.max_paper].</span>"
/obj/item/modular_computer/add_context(atom/source, list/context, obj/item/held_item, mob/user)
. = ..()
@@ -354,11 +380,6 @@ GLOBAL_LIST_EMPTY(TabletMessengers) // a list of all active messengers, similar
to_chat(user, span_warning("You press the power button, but the computer fails to boot up, displaying variety of errors before shutting down again."))
return FALSE
// If we have a recharger, enable it automatically. Lets computer without a battery work.
var/obj/item/computer_hardware/recharger/recharger = all_components[MC_CHARGE]
if(recharger)
recharger.enabled = 1
if(use_power()) // use_power() checks if the PC is powered
if(issynth)
to_chat(user, span_notice("You send an activation signal to \the [src], turning it on."))
@@ -403,8 +424,7 @@ GLOBAL_LIST_EMPTY(TabletMessengers) // a list of all active messengers, similar
else
active_program = null
for(var/I in idle_threads)
var/datum/computer_file/program/P = I
for(var/datum/computer_file/program/P as anything in idle_threads)
if(P.program_state != PROGRAM_STATE_KILLED)
P.process_tick(delta_time)
P.ntnet_status = get_ntnet_status()
@@ -417,7 +437,7 @@ GLOBAL_LIST_EMPTY(TabletMessengers) // a list of all active messengers, similar
/**
* Displays notification text alongside a soundbeep when requested to by a program.
*
* After checking tha the requesting program is allowed to send an alert, creates
* After checking that the requesting program is allowed to send an alert, creates
* a visible message of the requested text alongside a soundbeep. This proc adds
* text to indicate that the message is coming from this device and the program
* on it, so the supplied text should be the exact message and ending punctuation.
@@ -426,15 +446,11 @@ GLOBAL_LIST_EMPTY(TabletMessengers) // a list of all active messengers, similar
* The program calling this proc.
* The message that the program wishes to display.
*/
/obj/item/modular_computer/proc/alert_call(datum/computer_file/program/caller, alerttext, sound = 'sound/machines/twobeep_high.ogg')
if(!caller || !caller.alert_able || caller.alert_silenced || !alerttext) //Yeah, we're checking alert_able. No, you don't get to make alerts that the user can't silence.
return
return FALSE
playsound(src, sound, 50, TRUE)
visible_message(span_notice("The [src] displays a [caller.filedesc] notification: [alerttext]"))
var/mob/living/holder = loc
if(istype(holder))
to_chat(holder, "[icon2html(src)] [span_notice("The [src] displays a [caller.filedesc] notification: [alerttext]")]")
visible_message(span_notice("[icon2html(src)] [span_notice("The [src] displays a [caller.filedesc] notification: [alerttext]")]"))
/obj/item/modular_computer/proc/ring(ringtone) // bring bring
if(HAS_TRAIT(SSstation, STATION_TRAIT_PDA_GLITCHED))
@@ -453,7 +469,6 @@ GLOBAL_LIST_EMPTY(TabletMessengers) // a list of all active messengers, similar
data["PC_device_theme"] = device_theme
var/obj/item/computer_hardware/battery/battery_module = all_components[MC_CELL]
var/obj/item/computer_hardware/recharger/recharger = all_components[MC_CHARGE]
if(battery_module && battery_module.battery)
switch(battery_module.battery.percent())
@@ -476,9 +491,6 @@ GLOBAL_LIST_EMPTY(TabletMessengers) // a list of all active messengers, similar
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"
@@ -582,9 +594,9 @@ GLOBAL_LIST_EMPTY(TabletMessengers) // a list of all active messengers, similar
idle_threads.Remove(P)
if(looping_sound)
soundloop.stop()
if(loud)
if(physical && loud)
physical.visible_message(span_notice("\The [src] shuts down."))
enabled = 0
enabled = FALSE
update_appearance()
/obj/item/modular_computer/ui_action_click(mob/user, actiontype)
@@ -668,9 +680,10 @@ GLOBAL_LIST_EMPTY(TabletMessengers) // a list of all active messengers, similar
to_chat(user, span_notice("You slot \the [attacking_item] into [src]."))
return
var/obj/item/computer_hardware/hard_drive/hdd = all_components[MC_HDD]
// Scan a photo.
if(istype(attacking_item, /obj/item/photo))
var/obj/item/computer_hardware/hard_drive/hdd = all_components[MC_HDD]
var/obj/item/photo/pic = attacking_item
if(hdd)
for(var/datum/computer_file/program/messenger/messenger in hdd.stored_files)
@@ -684,6 +697,11 @@ GLOBAL_LIST_EMPTY(TabletMessengers) // a list of all active messengers, similar
if(H.try_insert(attacking_item, user))
return
// Insert items into applications
for(var/datum/computer_file/item_holding_app as anything in hdd.stored_files)
if(item_holding_app.try_insert(attacking_item, user))
return
// Insert new hardware
if(istype(attacking_item, /obj/item/computer_hardware) && upgradable)
if(install_component(attacking_item, user))
@@ -3,14 +3,13 @@
if(check_power_override())
return TRUE
var/obj/item/computer_hardware/recharger/recharger = all_components[MC_CHARGE]
if(recharger?.check_functionality())
if(recharger.use_power(amount))
if(ismachinery(loc))
var/obj/machinery/machine_holder = loc
if(machine_holder.powered())
machine_holder.use_power(amount)
return TRUE
var/obj/item/computer_hardware/battery/battery_module = all_components[MC_CELL]
if(battery_module && battery_module.battery && battery_module.battery.charge)
var/obj/item/stock_parts/cell/cell = battery_module.battery
if(cell.use(amount JOULES))
@@ -42,10 +41,6 @@
// Handles power-related things, such as battery interaction, recharging, shutdown when it's discharged
/obj/item/modular_computer/proc/handle_power(delta_time)
var/obj/item/computer_hardware/recharger/recharger = all_components[MC_CHARGE]
if(recharger)
recharger.process(delta_time)
var/power_usage = screen_on ? base_active_power_usage : base_idle_power_usage
for(var/obj/item/computer_hardware/H in all_components)
@@ -59,6 +54,10 @@
power_failure()
return FALSE
// Used by child types if they have other power source than battery or recharger
///Used by subtypes for special cases for power usage, returns TRUE if it should stop the use_power chain.
/obj/item/modular_computer/proc/check_power_override()
return FALSE
//Integrated (Silicon) tablets don't drain power, because the tablet is required to state laws, so it being disabled WILL cause problems.
/obj/item/modular_computer/tablet/integrated/check_power_override()
return TRUE
@@ -89,18 +89,19 @@
IDJob = cardholder.current_job,
)
var/obj/item/computer_hardware/hard_drive/hard_drive = all_components[MC_HDD]
data["removable_media"] = list()
if(all_components[MC_SDD])
data["removable_media"] += "Eject Disk"
var/obj/item/computer_hardware/ai_slot/intelliholder = all_components[MC_AI]
if(intelliholder?.stored_card)
var/datum/computer_file/program/ai_restorer/airestore_app = locate() in hard_drive.stored_files
if(airestore_app?.stored_card)
data["removable_media"] += "intelliCard"
var/obj/item/computer_hardware/card_slot/secondarycardholder = all_components[MC_CARD2]
if(secondarycardholder?.stored_card)
data["removable_media"] += "secondary RFID card"
data["programs"] = list()
var/obj/item/computer_hardware/hard_drive/hard_drive = all_components[MC_HDD]
for(var/datum/computer_file/program/P in hard_drive.stored_files)
var/running = FALSE
if(P in idle_threads)
@@ -189,10 +190,10 @@
user.put_in_hands(portable_drive)
playsound(src, 'sound/machines/card_slide.ogg', 50)
if("intelliCard")
var/obj/item/computer_hardware/ai_slot/intelliholder = all_components[MC_AI]
if(!intelliholder)
var/datum/computer_file/program/ai_restorer/airestore_app = locate() in hard_drive.stored_files
if(!airestore_app)
return
if(intelliholder.try_eject(user))
if(airestore_app.try_eject(user))
playsound(src, 'sound/machines/card_slide.ogg', 50)
if("ID")
var/obj/item/computer_hardware/card_slot/cardholder = all_components[MC_CARD]
@@ -2,7 +2,7 @@
//TODO: REFACTOR THIS SPAGHETTI CODE, MAKE IT A COMPUTER_HARDWARE COMPONENT OR REMOVE IT
/obj/item/modular_computer/processor
name = "processing unit"
desc = "You shouldn't see this. If you do, report it."
desc = "An advanced computer." //modular PCs examine us
icon = null
icon_state = null
icon_state_unpowered = null
@@ -50,12 +50,3 @@
..()
machinery_computer.update_appearance()
return
/obj/item/modular_computer/processor/attack_ghost(mob/user)
ui_interact(user)
/obj/item/modular_computer/processor/alert_call(datum/computer_file/program/caller, alerttext)
if(!caller || !caller.alert_able || caller.alert_silenced || !alerttext)
return
playsound(src, 'sound/machines/twobeep_high.ogg', 50, TRUE)
machinery_computer.visible_message(span_notice("The [src] displays a [caller.filedesc] notification: [alerttext]"))
@@ -21,7 +21,7 @@
name = "captain PDA"
greyscale_config = /datum/greyscale_config/tablet/captain
greyscale_colors = "#2C7CB2#FF0000#FFFFFF#FFD55B"
insert_type = /obj/item/pen/fountain/captain
inserted_item = /obj/item/pen/fountain/captain
/obj/item/modular_computer/tablet/pda/heads/captain/Initialize(mapload)
. = ..()
@@ -92,7 +92,7 @@
name = "research director PDA"
greyscale_config = /datum/greyscale_config/tablet/stripe_thick/head
greyscale_colors = "#FAFAFA#000099#B347BC"
insert_type = /obj/item/pen/fountain
inserted_item = /obj/item/pen/fountain
default_applications = list(
/datum/computer_file/program/crew_manifest,
/datum/computer_file/program/status,
@@ -111,7 +111,7 @@
name = "quartermaster PDA"
greyscale_config = /datum/greyscale_config/tablet/stripe_thick
greyscale_colors = "#D6B328#6506CA#927444"
insert_type = /obj/item/pen/survival
inserted_item = /obj/item/pen/survival
default_applications = list(
/datum/computer_file/program/crew_manifest,
/datum/computer_file/program/status,
@@ -287,7 +287,7 @@
/obj/item/modular_computer/tablet/pda/lawyer
name = "lawyer PDA"
greyscale_colors = "#4C76C8#FFE243"
insert_type = /obj/item/pen/fountain
inserted_item = /obj/item/pen/fountain
default_applications = list(
/datum/computer_file/program/records/security,
)
@@ -319,7 +319,7 @@
icon_state = "pda-clown"
greyscale_config = null
greyscale_colors = null
insert_type = /obj/item/toy/crayon/rainbow
inserted_item = /obj/item/toy/crayon/rainbow
/obj/item/modular_computer/tablet/pda/clown/Initialize(mapload)
. = ..()
@@ -345,7 +345,7 @@
loaded_cartridge = /obj/item/computer_hardware/hard_drive/portable/virus/mime
greyscale_config = /datum/greyscale_config/tablet/mime
greyscale_colors = "#FAFAFA#EA3232"
insert_type = /obj/item/toy/crayon/mime
inserted_item = /obj/item/toy/crayon/mime
/obj/item/modular_computer/tablet/pda/mime/Initialize(mapload)
. = ..()
@@ -361,7 +361,7 @@
greyscale_config = null
greyscale_colors = null
icon_state = "pda-library"
insert_type = /obj/item/pen/fountain
inserted_item = /obj/item/pen/fountain
default_applications = list(
/datum/computer_file/program/newscaster,
)
@@ -27,10 +27,7 @@
var/finish_color = null
var/list/contained_item = list(/obj/item/pen, /obj/item/toy/crayon, /obj/item/lipstick, /obj/item/flashlight/pen, /obj/item/clothing/mask/cigarette)
var/obj/item/insert_type = /obj/item/pen
var/obj/item/inserted_item
var/note = "Congratulations on your station upgrading to the new NtOS and Thinktronic based collaboration effort, bringing you the best in electronics and software since 2467!" // the note used by the notekeeping app, stored here for convenience
var/obj/item/inserted_item = /obj/item/pen
/obj/item/modular_computer/tablet/update_icon_state()
if(has_variants && !bypass_state)
@@ -255,12 +252,6 @@
robo.toggle_headlamp(FALSE, TRUE)
return TRUE
/obj/item/modular_computer/tablet/integrated/alert_call(datum/computer_file/program/caller, alerttext, sound = 'sound/machines/twobeep_high.ogg')
if(!caller || !caller.alert_able || caller.alert_silenced || !alerttext) //Yeah, we're checking alert_able. No, you don't get to make alerts that the user can't silence.
return
borgo.playsound_local(src, sound, 50, TRUE)
to_chat(borgo, span_notice("The [src] displays a [caller.filedesc] notification: [alerttext]"))
/obj/item/modular_computer/tablet/integrated/ui_state(mob/user)
return GLOB.reverse_contained_state
@@ -326,5 +317,5 @@
var/obj/item/computer_hardware/hard_drive/portable/disk = new loaded_cartridge(src)
install_component(disk)
if(insert_type)
inserted_item = new insert_type(src)
if(inserted_item)
inserted_item = new inserted_item(src)
@@ -1,93 +1,3 @@
// This is literally the worst possible cheap tablet
/obj/item/modular_computer/tablet/preset/cheap
desc = "A low-end tablet often seen among low ranked station personnel."
/obj/item/modular_computer/tablet/preset/cheap/Initialize(mapload)
. = ..()
install_component(new /obj/item/computer_hardware/battery(src, /obj/item/stock_parts/cell/computer/micro))
install_component(new /obj/item/computer_hardware/hard_drive/small)
install_component(new /obj/item/computer_hardware/network_card)
// Alternative version, an average one, for higher ranked positions mostly
/obj/item/modular_computer/tablet/preset/advanced/Initialize(mapload)
. = ..()
install_component(new /obj/item/computer_hardware/battery(src, /obj/item/stock_parts/cell/computer))
install_component(new /obj/item/computer_hardware/hard_drive/small)
install_component(new /obj/item/computer_hardware/network_card)
install_component(new /obj/item/computer_hardware/card_slot)
install_component(new /obj/item/computer_hardware/printer/mini)
/obj/item/modular_computer/tablet/preset/science/Initialize(mapload)
. = ..()
var/obj/item/computer_hardware/hard_drive/small/hard_drive = new
install_component(new /obj/item/computer_hardware/battery(src, /obj/item/stock_parts/cell/computer))
install_component(hard_drive)
install_component(new /obj/item/computer_hardware/card_slot)
install_component(new /obj/item/computer_hardware/network_card)
hard_drive.store_file(new /datum/computer_file/program/signal_commander)
/obj/item/modular_computer/tablet/preset/cargo/Initialize(mapload)
. = ..()
var/obj/item/computer_hardware/hard_drive/small/hard_drive = new
install_component(new /obj/item/computer_hardware/battery(src, /obj/item/stock_parts/cell/computer))
install_component(hard_drive)
install_component(new /obj/item/computer_hardware/card_slot)
install_component(new /obj/item/computer_hardware/network_card)
install_component(new /obj/item/computer_hardware/printer/mini)
hard_drive.store_file(new /datum/computer_file/program/shipping)
var/datum/computer_file/program/chatclient/chatprogram
chatprogram = new
hard_drive.store_file(chatprogram)
chatprogram.username = get_cargochat_username()
/obj/item/modular_computer/tablet/preset/cargo/proc/get_cargochat_username()
return "cargonian_[rand(1,999)]"
/obj/item/modular_computer/tablet/preset/cargo/quartermaster/get_cargochat_username()
return "quartermaster"
/obj/item/modular_computer/tablet/preset/advanced/atmos/Initialize(mapload) //This will be defunct and will be replaced when NtOS PDAs are done
. = ..()
var/obj/item/computer_hardware/hard_drive/small/hard_drive = find_hardware_by_name("solid state drive")
hard_drive.store_file(new /datum/computer_file/program/alarm_monitor)
hard_drive.store_file(new /datum/computer_file/program/atmosscan)
/obj/item/modular_computer/tablet/preset/advanced/custodial/Initialize(mapload)
. = ..()
var/obj/item/computer_hardware/hard_drive/small/hard_drive = find_hardware_by_name("solid state drive")
hard_drive.store_file(new /datum/computer_file/program/radar/custodial_locator)
/obj/item/modular_computer/tablet/preset/advanced/curator/Initialize(mapload)
. = ..()
var/obj/item/computer_hardware/hard_drive/small/hard_drive = find_hardware_by_name("solid state drive")
hard_drive.store_file(new /datum/computer_file/program/newscaster)
/obj/item/modular_computer/tablet/preset/advanced/engineering/Initialize(mapload)
. = ..()
var/obj/item/computer_hardware/hard_drive/small/hard_drive = find_hardware_by_name("solid state drive")
hard_drive.store_file(new /datum/computer_file/program/alarm_monitor)
hard_drive.store_file(new /datum/computer_file/program/supermatter_monitor)
/obj/item/modular_computer/tablet/preset/advanced/security/Initialize(mapload)
. = ..()
var/obj/item/computer_hardware/hard_drive/small/hard_drive = find_hardware_by_name("solid state drive")
hard_drive.store_file(new /datum/computer_file/program/crew_manifest)
hard_drive.store_file(new /datum/computer_file/program/robocontrol)
/obj/item/modular_computer/tablet/preset/advanced/command/Initialize(mapload)
. = ..()
var/obj/item/computer_hardware/hard_drive/small/hard_drive = find_hardware_by_name("solid state drive")
install_component(new /obj/item/computer_hardware/card_slot/secondary)
hard_drive.store_file(new /datum/computer_file/program/budgetorders)
hard_drive.store_file(new /datum/computer_file/program/science)
/obj/item/modular_computer/tablet/preset/advanced/command/engineering/Initialize(mapload)
. = ..()
var/obj/item/computer_hardware/hard_drive/small/hard_drive = find_hardware_by_name("solid state drive")
hard_drive.store_file(new /datum/computer_file/program/alarm_monitor)
hard_drive.store_file(new /datum/computer_file/program/supermatter_monitor)
/// Given to Nuke Ops members.
/obj/item/modular_computer/tablet/nukeops/Initialize(mapload)
. = ..()
@@ -98,5 +8,4 @@
//Borg Built-in tablet
/obj/item/modular_computer/tablet/integrated/Initialize(mapload)
. = ..()
install_component(new /obj/item/computer_hardware/recharger/cyborg)
install_component(new /obj/item/computer_hardware/network_card/integrated)
@@ -3,7 +3,6 @@
var/_has_second_id_slot = FALSE
var/_has_printer = FALSE
var/_has_battery = FALSE
var/_has_ai = FALSE
/obj/machinery/modular_computer/console/preset/Initialize(mapload)
. = ..()
@@ -17,8 +16,6 @@
cpu.install_component(new /obj/item/computer_hardware/printer)
if(_has_battery)
cpu.install_component(new /obj/item/computer_hardware/battery(cpu, /obj/item/stock_parts/cell/computer/super))
if(_has_ai)
cpu.install_component(new /obj/item/computer_hardware/ai_slot)
install_programs()
// Override in child types to install preset-specific programs.
@@ -43,13 +40,12 @@
name = "research director's console"
desc = "A stationary computer. This one comes preloaded with research programs."
_has_second_id_slot = TRUE
_has_ai = TRUE
/obj/machinery/modular_computer/console/preset/research/install_programs()
var/obj/item/computer_hardware/hard_drive/hard_drive = cpu.all_components[MC_HDD]
hard_drive.store_file(new/datum/computer_file/program/ntnetmonitor())
hard_drive.store_file(new/datum/computer_file/program/chatclient())
hard_drive.store_file(new/datum/computer_file/program/aidiag())
hard_drive.store_file(new/datum/computer_file/program/ai_restorer())
hard_drive.store_file(new/datum/computer_file/program/robocontrol())
hard_drive.store_file(new/datum/computer_file/program/scipaper_program())
@@ -2,12 +2,12 @@
// DO NOT SPAWN THIS TYPE. Use /laptop/ or /console/ instead.
/obj/machinery/modular_computer
name = "modular computer"
desc = "An advanced computer."
desc = "You shouldn't see this. If you do, report it." //they should be examining the processor instead
// 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 = null
icon = 'icons/obj/modular_console.dmi'
icon_state = null
idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION * 0.05
@@ -39,7 +39,7 @@
var/base_idle_power_usage = 10
///CPU that handles most logic while this type only handles power and other specific things.
var/obj/item/modular_computer/processor/cpu = null
var/obj/item/modular_computer/processor/cpu
/obj/machinery/modular_computer/Initialize(mapload)
. = ..()
@@ -51,8 +51,9 @@
return ..()
/obj/machinery/modular_computer/examine(mob/user)
. = ..()
. += get_modular_computer_parts_examine(user)
if(cpu)
return cpu.examine(user)
return ..()
/obj/machinery/modular_computer/attack_ghost(mob/dead/observer/user)
. = ..()
@@ -65,27 +66,33 @@
if(!cpu)
to_chat(user, span_warning("You'd need to turn the [src] on first."))
return FALSE
return (cpu.emag_act(user))
return cpu.emag_act(user)
/obj/machinery/modular_computer/update_appearance(updates)
. = ..()
set_light(cpu?.enabled ? light_strength : 0)
/obj/machinery/modular_computer/update_icon_state()
icon_state = (cpu?.enabled || (!(machine_stat & NOPOWER) && cpu?.use_power())) ? icon_state_powered : icon_state_unpowered
if(!cpu || !cpu.enabled || !cpu.use_power() || (machine_stat & NOPOWER))
icon_state = icon_state_unpowered
else
icon_state = icon_state_powered
return ..()
/obj/machinery/modular_computer/update_overlays()
. = ..()
if(!cpu?.enabled)
if (!(machine_stat & NOPOWER) && (cpu?.use_power()))
. += screen_icon_screensaver
else
. += cpu.active_program?.program_icon_state || screen_icon_state_menu
if(!cpu)
return .
if(cpu && cpu.get_integrity() <= cpu.integrity_failure * cpu.max_integrity)
if(cpu.enabled && cpu.use_power())
. += cpu.active_program?.program_icon_state || screen_icon_state_menu
else if(!(machine_stat & NOPOWER))
. += screen_icon_screensaver
if(cpu.get_integrity() <= cpu.integrity_failure * cpu.max_integrity)
. += "bsod"
. += "broken"
return .
/// Eats the "source" arg because update_icon actually expects args now.
/obj/machinery/modular_computer/proc/relay_icon_update(datum/source, updates, updated)
@@ -103,9 +110,8 @@
// On-click handling. Turns on the computer if it's off and opens the GUI.
/obj/machinery/modular_computer/interact(mob/user)
if(cpu)
return cpu.interact(user) // CPU is an item, that's why we route attack_hand to attack_self
else
return ..()
return cpu.interact(user)
return ..()
// Process currently calls handle_power(), may be expanded in future if more things are added.
/obj/machinery/modular_computer/process(delta_time)
@@ -114,33 +120,23 @@
cpu.name = name
cpu.process(delta_time)
// Used in following function to reduce copypaste
/obj/machinery/modular_computer/proc/power_failure(malfunction = 0)
var/obj/item/computer_hardware/battery/battery_module = cpu.all_components[MC_CELL]
if(cpu?.enabled) // Shut down the computer
visible_message(span_danger("\The [src]'s screen flickers [battery_module ? "\"BATTERY [malfunction ? "MALFUNCTION" : "CRITICAL"]\"" : "\"EXTERNAL POWER LOSS\""] warning as it shuts down unexpectedly."))
if(cpu)
cpu.shutdown_computer(0)
set_machine_stat(machine_stat | NOPOWER)
update_appearance()
// Modular computers can have battery in them, we handle power in previous proc, so prevent this from messing it up for us.
/obj/machinery/modular_computer/power_change()
if(cpu?.use_power()) // If it still has a power source, PC wouldn't go offline.
set_machine_stat(machine_stat & ~NOPOWER)
update_appearance()
return
. = ..()
return ..()
/obj/machinery/modular_computer/screwdriver_act(mob/user, obj/item/tool)
if(cpu)
return cpu.screwdriver_act(user, tool)
/obj/machinery/modular_computer/attackby(obj/item/W as obj, mob/living/user)
if (!user.combat_mode && cpu && !(flags_1 & NODECONSTRUCT_1))
return cpu.attackby(W, user)
return ..()
/obj/machinery/modular_computer/attackby(obj/item/W as obj, mob/living/user)
if (cpu && !user.combat_mode && !(flags_1 & NODECONSTRUCT_1))
return cpu.attackby(W, user)
return ..()
// Stronger explosions cause serious damage to internal components
// Minor explosions are mostly mitigitated by casing.
@@ -170,4 +166,5 @@
// "Brute" damage mostly damages the casing.
/obj/machinery/modular_computer/bullet_act(obj/projectile/Proj)
if(cpu)
cpu.bullet_act(Proj)
return cpu.bullet_act(Proj)
return ..()
@@ -6,7 +6,6 @@
icon_state = "console"
icon_state_powered = "console"
icon_state_unpowered = "console-off"
screen_icon_state_menu = "menu"
hardware_flag = PROGRAM_CONSOLE
density = TRUE
base_idle_power_usage = 100
@@ -24,10 +23,8 @@
// User-built consoles start as empty frames.
var/obj/item/computer_hardware/hard_drive/hard_drive = cpu.all_components[MC_HDD]
var/obj/item/computer_hardware/hard_drive/network_card = cpu.all_components[MC_NET]
var/obj/item/computer_hardware/hard_drive/recharger = cpu.all_components[MC_CHARGE]
qdel(recharger)
qdel(network_card)
qdel(hard_drive)
qdel(network_card)
/obj/machinery/modular_computer/console/Initialize(mapload)
. = ..()
@@ -38,7 +35,6 @@
var/obj/item/computer_hardware/network_card/wired/network_card = new()
cpu.install_component(network_card)
cpu.install_component(new /obj/item/computer_hardware/recharger/apc_recharger)
cpu.install_component(new /obj/item/computer_hardware/hard_drive/super) // Consoles generally have better HDDs due to lower space limitations
var/area/A = get_area(src)
@@ -13,7 +13,7 @@
..()
uid = file_uid++
/datum/computer_file/Destroy()
/datum/computer_file/Destroy(force)
if(!holder)
return ..()
@@ -37,3 +37,29 @@
temp.filename = filename
temp.filetype = filetype
return temp
/**
* Called when examining a modular computer
* Args:
* Source - The tablet that's being examined
* User - Person examining the computer
*
* note: please replace this with signals when hdd's are removed and program's New() already has the tablet set.
*/
/datum/computer_file/proc/on_examine(obj/item/modular_computer/source, mob/user)
return null
/// Called when someone tries to insert something one of your applications needs, like an Intellicard for AI restoration.
/datum/computer_file/proc/try_insert(obj/item/attacking_item, mob/living/user)
return FALSE
/**
* Implement this when your program has an object that the user can eject.
*
* Examples include ejecting cells AI intellicards.
* Arguments:
* * user - The mob requesting the eject.
* * forced - Whether we are forced to eject everything (usually by the app being deleted)
*/
/datum/computer_file/proc/try_eject(mob/living/user, forced = FALSE)
return FALSE
@@ -1,127 +1,139 @@
/datum/computer_file/program/aidiag
filename = "aidiag"
filedesc = "NT FRK"
/datum/computer_file/program/ai_restorer
filename = "ai_restore"
filedesc = "AI Manager & Restorer"
category = PROGRAM_CATEGORY_SCI
program_icon_state = "generic"
extended_desc = "Firmware Restoration Kit, capable of reconstructing damaged AI systems. Requires direct AI connection via intellicard slot."
size = 12
requires_ntnet = FALSE
usage_flags = PROGRAM_CONSOLE | PROGRAM_LAPTOP
transfer_access = list(ACCESS_COMMAND)
transfer_access = list(ACCESS_RD)
available_on_ntnet = TRUE
tgui_id = "NtosAiRestorer"
program_icon = "laptop-code"
/// The AI stored in the program
var/obj/item/aicard/stored_card
/// Variable dictating if we are in the process of restoring the AI in the inserted intellicard
var/restoring = FALSE
/datum/computer_file/program/aidiag/proc/get_ai(cardcheck)
/datum/computer_file/program/ai_restorer/on_examine(obj/item/modular_computer/source, mob/user)
var/list/examine_text = list()
if(!stored_card)
examine_text += "It has a slot installed for an intelliCard."
return examine_text
var/obj/item/computer_hardware/ai_slot/ai_slot
if(computer.Adjacent(user))
examine_text += "It has a slot installed for an intelliCard which contains: [stored_card.name]"
else
examine_text += "It has a slot installed for an intelliCard, which appears to be occupied."
examine_text += span_info("Alt-click to eject the intelliCard.")
return examine_text
if(computer)
ai_slot = computer.all_components[MC_AI]
/datum/computer_file/program/ai_restorer/kill_program(forced)
try_eject(forced = TRUE)
return ..()
if(computer && ai_slot?.check_functionality())
if(cardcheck == 1)
return ai_slot
if(ai_slot.enabled && ai_slot.stored_card)
if(cardcheck == 2)
return ai_slot.stored_card
if(ai_slot.stored_card.AI)
return ai_slot.stored_card.AI
return
/datum/computer_file/program/aidiag/ui_act(action, params)
. = ..()
if(.)
return
var/mob/living/silicon/ai/A = get_ai()
if(!A)
restoring = FALSE
switch(action)
if("PRG_beginReconstruction")
if(A && A.health < 100)
restoring = TRUE
A.notify_ghost_cloning("Your core files are being restored!", source = computer)
return TRUE
if("PRG_eject")
if(computer.all_components[MC_AI])
var/obj/item/computer_hardware/ai_slot/ai_slot = computer.all_components[MC_AI]
if(ai_slot?.stored_card)
ai_slot.try_eject(usr)
return TRUE
/datum/computer_file/program/aidiag/process_tick()
/datum/computer_file/program/ai_restorer/process_tick(delta_time)
. = ..()
if(!restoring) //Put the check here so we don't check for an ai all the time
return
var/obj/item/aicard/cardhold = get_ai(2)
var/obj/item/computer_hardware/ai_slot/ai_slot = get_ai(1)
var/mob/living/silicon/ai/A = get_ai()
if(!A || !cardhold)
restoring = FALSE // If the AI was removed, stop the restoration sequence.
if(ai_slot)
ai_slot.locked = FALSE
return
if(cardhold.flush)
ai_slot.locked = FALSE
var/mob/living/silicon/ai/A = stored_card.AI
if(stored_card.flush)
restoring = FALSE
return
ai_slot.locked = TRUE
A.adjustOxyLoss(-5, FALSE)
A.adjustFireLoss(-5, FALSE)
A.adjustBruteLoss(-5, FALSE)
// Please don't forget to update health, otherwise the below if statements will probably always fail.
A.updatehealth()
if(A.health >= 0 && A.stat == DEAD)
A.revive(full_heal = FALSE, admin_revive = FALSE)
cardhold.update_appearance()
stored_card.update_appearance()
// Finished restoring
if(A.health >= 100)
ai_slot.locked = FALSE
restoring = FALSE
return TRUE
/datum/computer_file/program/ai_restorer/try_insert(obj/item/attacking_item, mob/living/user)
if(!computer)
return FALSE
if(!istype(attacking_item, /obj/item/aicard))
return FALSE
/datum/computer_file/program/aidiag/ui_data(mob/user)
if(stored_card)
to_chat(user, span_warning("You try to insert \the [attacking_item] into \the [computer.name], but the slot is occupied."))
return FALSE
if(user && !user.transferItemToLoc(attacking_item, computer))
return FALSE
stored_card = attacking_item
to_chat(user, span_notice("You insert \the [attacking_item] into \the [computer.name]."))
return TRUE
/datum/computer_file/program/ai_restorer/try_eject(mob/living/user, forced = FALSE)
if(!stored_card)
if(user)
to_chat(user, span_warning("There is no card in \the [computer.name]."))
return FALSE
if(restoring && !forced)
if(user)
to_chat(user, span_warning("Safeties prevent you from removing the card until reconstruction is complete..."))
return FALSE
if(user && computer.Adjacent(user))
to_chat(user, span_notice("You remove [stored_card] from [computer.name]."))
user.put_in_hands(stored_card)
else
stored_card.forceMove(computer.drop_location())
stored_card = null
restoring = FALSE
return TRUE
/datum/computer_file/program/ai_restorer/ui_act(action, params)
. = ..()
if(.)
return
switch(action)
if("PRG_beginReconstruction")
if(!stored_card || !stored_card.AI)
return FALSE
var/mob/living/silicon/ai/A = stored_card.AI
if(A && A.health < 100)
restoring = TRUE
A.notify_ghost_cloning("Your core files are being restored!", source = computer)
return TRUE
if("PRG_eject")
if(stored_card)
try_eject(usr)
return TRUE
/datum/computer_file/program/ai_restorer/ui_data(mob/user)
var/list/data = get_header_data()
var/mob/living/silicon/ai/AI = get_ai()
var/obj/item/aicard/aicard = get_ai(2)
data["ejectable"] = TRUE
data["AI_present"] = FALSE
data["AI_present"] = !!stored_card?.AI
data["error"] = null
if(!aicard)
if(!stored_card)
data["error"] = "Please insert an intelliCard."
else if(!stored_card.AI)
data["error"] = "No AI located..."
else if(stored_card.flush)
data["error"] = "Flush in progress!"
else
if(!AI)
data["error"] = "No AI located"
else
var/obj/item/aicard/cardhold = AI.loc
if(cardhold.flush)
data["error"] = "Flush in progress"
else
data["AI_present"] = TRUE
data["name"] = AI.name
data["restoring"] = restoring
data["health"] = (AI.health + 100) / 2
data["isDead"] = AI.stat == DEAD
data["laws"] = AI.laws.get_law_list(include_zeroth = TRUE, render_html = FALSE)
data["name"] = stored_card.AI.name
data["restoring"] = restoring
data["health"] = (stored_card.AI.health + 100) / 2
data["isDead"] = stored_card.AI.stat == DEAD
data["laws"] = stored_card.AI.laws.get_law_list(include_zeroth = TRUE, render_html = FALSE)
return data
/datum/computer_file/program/aidiag/kill_program(forced)
restoring = FALSE
return ..()
@@ -26,7 +26,7 @@
QDEL_NULL(alert_control)
return ..()
/datum/computer_file/program/alarm_monitor/process_tick()
/datum/computer_file/program/alarm_monitor/process_tick(delta_time)
..()
if(has_alert)
@@ -16,7 +16,7 @@
var/error = ""
var/executed = 0
/datum/computer_file/program/ntnet_dos/process_tick()
/datum/computer_file/program/ntnet_dos/process_tick(delta_time)
dos_speed = 0
switch(ntnet_status)
if(1)
@@ -30,7 +30,6 @@
computer.update_appearance()
var/obj/item/computer_hardware/hard_drive/hard_drive = computer.all_components[MC_HDD]
var/obj/item/computer_hardware/battery/battery_module = computer.all_components[MC_CELL]
var/obj/item/computer_hardware/recharger/recharger = computer.all_components[MC_CHARGE]
qdel(hard_drive)
computer.take_damage(25, BRUTE, 0, 0)
if(battery_module && prob(25))
@@ -39,12 +38,6 @@
var/datum/effect_system/spark_spread/spark_system = new /datum/effect_system/spark_spread
spark_system.start()
if(recharger && prob(50))
qdel(recharger)
computer.visible_message(span_notice("\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)
. = ..()
@@ -47,7 +47,7 @@
borgo.logevent("File request by [username]: /var/logs/syslog")
return TRUE
/datum/computer_file/program/borg_monitor/process_tick()
/datum/computer_file/program/borg_monitor/process_tick(delta_time)
if(!DL_source)
DL_progress = -1
return
@@ -9,6 +9,9 @@
program_icon = "book"
usage_flags = PROGRAM_TABLET
var/written_note = "Congratulations on your station upgrading to the new NtOS and Thinktronic based collaboration effort, \
bringing you the best in electronics and software since 2467!"
/datum/computer_file/program/notepad/ui_act(action, list/params, datum/tgui/ui)
. = ..()
if(.)
@@ -16,14 +19,12 @@
switch(action)
if("UpdateNote")
var/obj/item/modular_computer/tablet/comp = computer
comp.note = params["newnote"]
written_note = params["newnote"]
return UI_UPDATE
/datum/computer_file/program/notepad/ui_data(mob/user)
var/list/data = get_header_data()
var/obj/item/modular_computer/tablet/comp = computer
data["note"] = comp.note
data["note"] = written_note
return data
@@ -93,7 +93,7 @@
download_completion = FALSE
ui_header = "downloader_finished.gif"
/datum/computer_file/program/ntnetdownload/process_tick()
/datum/computer_file/program/ntnetdownload/process_tick(delta_time)
if(!downloaded_file)
return
if(download_completion >= downloaded_file.size)
@@ -171,7 +171,7 @@
channel.ping_user(src, pinged)
return TRUE
/datum/computer_file/program/chatclient/process_tick()
/datum/computer_file/program/chatclient/process_tick(delta_time)
. = ..()
var/datum/ntnet_conversation/channel = SSnetworks.station_network.get_chat_channel_by_id(active_channel)
if(program_state != PROGRAM_STATE_KILLED)
@@ -31,7 +31,7 @@
history["demand"] = list()
/datum/computer_file/program/power_monitor/process_tick()
/datum/computer_file/program/power_monitor/process_tick(delta_time)
if(!get_powernet())
search()
else
@@ -197,7 +197,7 @@
computer.setDir(get_dir(here_turf, target_turf))
//We can use process_tick to restart fast processing, since the computer will be running this constantly either way.
/datum/computer_file/program/radar/process_tick()
/datum/computer_file/program/radar/process_tick(delta_time)
if(computer.active_program == src)
START_PROCESSING(SSfastprocess, src)
@@ -316,19 +316,13 @@
return
RegisterSignal(SSdcs, COMSIG_GLOB_NUKE_DEVICE_ARMED, .proc/on_nuke_armed)
if(computer)
RegisterSignal(computer, COMSIG_PARENT_EXAMINE, .proc/on_examine)
/datum/computer_file/program/radar/fission360/kill_program(forced)
UnregisterSignal(SSdcs, COMSIG_GLOB_NUKE_DEVICE_ARMED)
if(computer)
UnregisterSignal(computer, COMSIG_PARENT_EXAMINE)
return ..()
/datum/computer_file/program/radar/fission360/Destroy()
UnregisterSignal(SSdcs, COMSIG_GLOB_NUKE_DEVICE_ARMED)
if(computer)
UnregisterSignal(computer, COMSIG_PARENT_EXAMINE)
return ..()
/datum/computer_file/program/radar/fission360/find_atom()
@@ -364,16 +358,14 @@
)
objects += list(ship_info)
/*
* Signal proc for [COMSIG_PARENT_EXAMINE], registered on the computer.
* Shows how long any armed nukes are to detonating.
*/
/datum/computer_file/program/radar/fission360/proc/on_examine(datum/source, mob/user, list/examine_list)
SIGNAL_HANDLER
///Shows how long until the nuke detonates, if one is active.
/datum/computer_file/program/radar/fission360/on_examine(obj/item/modular_computer/source, mob/user)
var/list/examine_list = list()
for(var/obj/machinery/nuclearbomb/bomb as anything in GLOB.nuke_list)
if(bomb.timing)
examine_list += span_danger("Extreme danger. Arming signal detected. Time remaining: [bomb.get_time_left()].")
return examine_list
/*
* Signal proc for [COMSIG_GLOB_NUKE_DEVICE_ARMED].
@@ -392,4 +384,4 @@
computer.audible_message(
span_danger("[computer] vibrates and lets out an ominous alarm. Uh oh."),
span_notice("[computer] begins to vibrate rapidly. Wonder what that means..."),
)
)
@@ -20,7 +20,7 @@
active = null
return ..()
/datum/computer_file/program/supermatter_monitor/process_tick()
/datum/computer_file/program/supermatter_monitor/process_tick(delta_time)
..()
var/new_status = get_status()
if(last_status != new_status)
@@ -71,7 +71,8 @@
/// Called on multitool click, prints diagnostic information to the user.
/obj/item/computer_hardware/proc/diagnostics(mob/user)
to_chat(user, "Hardware Integrity Test... (Corruption: [damage]/[max_damage]) [damage > damage_failure ? "FAIL" : damage > damage_malfunction ? "WARN" : "PASS"]")
to_chat(user, "Hardware Integrity Test... (Corruption: [damage]/[max_damage]) \
[damage > damage_failure ? "FAIL" : damage > damage_malfunction ? "WARN" : "PASS"]")
/// Handles damage checks
/obj/item/computer_hardware/proc/check_functionality()
@@ -1,66 +0,0 @@
/obj/item/computer_hardware/ai_slot
name = "intelliCard interface slot"
desc = "A module allowing this computer to interface with most common intelliCard modules. Necessary for some programs to run properly."
power_usage = 100 //W
icon_state = "card_mini"
w_class = WEIGHT_CLASS_SMALL
device_type = MC_AI
expansion_hw = TRUE
var/obj/item/aicard/stored_card
var/locked = FALSE
///What happens when the intellicard is removed (or deleted) from the module, through try_eject() or not.
/obj/item/computer_hardware/ai_slot/Exited(atom/movable/gone, direction)
if(stored_card == gone)
stored_card = null
return ..()
/obj/item/computer_hardware/ai_slot/examine(mob/user)
. = ..()
if(stored_card)
. += "There appears to be an intelliCard loaded. There appears to be a pinhole protecting a manual eject button. A screwdriver could probably press it."
/obj/item/computer_hardware/ai_slot/try_insert(obj/item/I, mob/living/user = null)
if(!holder)
return FALSE
if(!istype(I, /obj/item/aicard))
return FALSE
if(stored_card)
to_chat(user, span_warning("You try to insert \the [I] into \the [src], but the slot is occupied."))
return FALSE
if(user && !user.transferItemToLoc(I, src))
return FALSE
stored_card = I
to_chat(user, span_notice("You insert \the [I] into \the [src]."))
return TRUE
/obj/item/computer_hardware/ai_slot/try_eject(mob/living/user = null, forced = FALSE)
if(!stored_card)
to_chat(user, span_warning("There is no card in \the [src]."))
return FALSE
if(locked && !forced)
to_chat(user, span_warning("Safeties prevent you from removing the card until reconstruction is complete..."))
return FALSE
if(stored_card)
to_chat(user, span_notice("You remove [stored_card] from [src]."))
locked = FALSE
if(Adjacent(user))
user.put_in_hands(stored_card)
else
stored_card.forceMove(drop_location())
return TRUE
return FALSE
/obj/item/computer_hardware/ai_slot/screwdriver_act(mob/living/user, obj/item/tool)
to_chat(user, span_notice("You press down on the manual eject button with [tool]."))
try_eject(user, TRUE)
return TOOL_ACT_TOOLTYPE_SUCCESS
@@ -4,8 +4,8 @@
icon_state = "cell_con"
critical = 1
malfunction_probability = 1
var/obj/item/stock_parts/cell/battery
device_type = MC_CELL
var/obj/item/stock_parts/cell/battery
/obj/item/computer_hardware/battery/get_cell()
return battery
@@ -88,6 +88,10 @@
return FALSE
if(F in stored_files)
if(istype(F, /datum/computer_file/program))
var/datum/computer_file/program/program_file = F
if(program_file.program_state != PROGRAM_STATE_KILLED)
program_file.kill_program(TRUE)
SEND_SIGNAL(F, COMSIG_MODULAR_COMPUTER_FILE_DELETING)
stored_files -= F
recalculate_size()
@@ -27,7 +27,6 @@
var/obj/item/paper/printed_paper = new/obj/item/paper(holder.drop_location())
// Damaged printer causes the resulting paper to be somewhat harder to read.
if(damage > damage_malfunction)
printed_paper.add_raw_text(stars(text_to_print, 100-malfunction_probability))
else
@@ -1,99 +0,0 @@
/obj/item/computer_hardware/recharger
critical = TRUE
enabled = TRUE
device_type = MC_CHARGE
var/charge_rate = 100
/obj/item/computer_hardware/recharger/proc/use_power(amount, charging=0)
if(charging)
return TRUE
return FALSE
/obj/item/computer_hardware/recharger/process()
..()
var/obj/item/computer_hardware/battery/battery_module = holder.all_components[MC_CELL]
if(!holder || !battery_module || !battery_module.battery)
return
var/obj/item/stock_parts/cell/cell = battery_module.battery
if(cell.charge >= cell.maxcharge)
return
if(use_power(charge_rate, charging=1))
holder.give_power(charge_rate JOULES)
/obj/item/computer_hardware/recharger/apc_recharger
name = "area power connector"
desc = "A device that wirelessly recharges connected device from nearby APC."
icon_state = "charger_APC"
w_class = WEIGHT_CLASS_SMALL // Can't be installed into tablets/PDAs
/obj/item/computer_hardware/recharger/apc_recharger/use_power(amount, charging=0)
if(ismachinery(holder.physical))
var/obj/machinery/M = holder.physical
if(M.powered())
M.use_power(amount)
return TRUE
else
var/area/A = get_area(src)
if(!istype(A))
return FALSE
if(A.powered(AREA_USAGE_EQUIP))
A.use_power(amount, AREA_USAGE_EQUIP)
return TRUE
return FALSE
/obj/item/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 = WEIGHT_CLASS_NORMAL
/obj/item/computer_hardware/recharger/wired/can_install(obj/item/modular_computer/install_into, mob/living/user = null)
if(ismachinery(install_into.physical) && install_into.physical.anchored)
return ..()
to_chat(user, span_warning("\The [src] is incompatible with portable computers!"))
return FALSE
/obj/item/computer_hardware/recharger/wired/use_power(amount, charging=0)
if(ismachinery(holder.physical) && holder.physical.anchored)
var/obj/machinery/M = holder.physical
var/turf/T = M.loc
if(!T || !istype(T))
return FALSE
var/obj/structure/cable/C = T.get_cable_node()
if(!C || !C.powernet)
return FALSE
var/power_in_net = C.powernet.avail-C.powernet.load
if(power_in_net && power_in_net > amount)
C.powernet.load += amount
return TRUE
return FALSE
/// This recharger exists only in borg built-in tablets. I would have tied it to the borg's cell but
/// the program that displays laws should always be usable, and the exceptions were starting to pile.
/obj/item/computer_hardware/recharger/cyborg
name = "modular interface power harness"
desc = "A standard connection to power a small computer device from a cyborg's chassis."
/obj/item/computer_hardware/recharger/cyborg/use_power(amount, charging=0)
return TRUE
// This is not intended to be obtainable in-game. Intended for adminbus and debugging purposes.
/obj/item/computer_hardware/recharger/lambda
name = "lambda coil"
desc = "A very complex device that draws power from its own bluespace dimension."
icon_state = "charger_lambda"
w_class = WEIGHT_CLASS_TINY
charge_rate = 100000
/obj/item/computer_hardware/recharger/lambda/use_power(amount, charging=0)
return 1
@@ -22,7 +22,6 @@
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_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
@@ -39,7 +38,6 @@
dev_battery = 1
dev_disk = 1
dev_netcard = 0
dev_apc_recharger = 0
dev_printer = 0
dev_card = 0
@@ -87,10 +85,6 @@
if(fabricate)
fabricated_laptop.install_component(new /obj/item/computer_hardware/network_card/advanced)
total_price += 299
if(dev_apc_recharger)
total_price += 399
if(fabricate)
fabricated_laptop.install_component(new /obj/item/computer_hardware/recharger/apc_recharger)
if(dev_printer)
total_price += 99
if(fabricate)
@@ -195,10 +189,6 @@
dev_netcard = text2num(params["netcard"])
fabricate_and_recalc_price(FALSE)
return TRUE
if("hw_tesla")
dev_apc_recharger = text2num(params["tesla"])
fabricate_and_recalc_price(FALSE)
return TRUE
if("hw_nanoprint")
dev_printer = text2num(params["print"])
fabricate_and_recalc_price(FALSE)
@@ -266,7 +256,6 @@
data["hw_battery"] = dev_battery
data["hw_disk"] = dev_disk
data["hw_netcard"] = dev_netcard
data["hw_tesla"] = dev_apc_recharger
data["hw_nanoprint"] = dev_printer
data["hw_card"] = dev_card
if(state == 1 || state == 2)