Removes ID computer parts (Removes computer hardware) (#71320)

## About The Pull Request

Removes the last computer part in the game: ID parts
Because this is removed, I also removed all computer hardware in the
game, and removed mentions of it in the game.
There is still 'hardware', as in Computer, Tablet, or Laptop.

Computers now all hold one ID slot by default, the only time a second ID
was needed was to use the access of both at once, and for the ID
modification application. This was now replaced with a new UI that only
has one tab, one ID slot:


https://user-images.githubusercontent.com/53777086/202801939-151b783f-75c8-46bf-a6c5-1b57b0d0da8e.mp4

## Why It's Good For The Game

Computer hardware is finally dead 🦀 

## Changelog

🆑
balance: All modular computers now only have one ID slot, and cannot be
upgraded.
qol: The HoP's access application now only has one app, logging in will
directly modify the ID that's in it, making it less confusing to swap
back and forth.
/🆑
This commit is contained in:
John Willard
2022-11-21 02:04:45 -05:00
committed by GitHub
parent 819d9d9082
commit b8d86849c8
42 changed files with 284 additions and 1092 deletions
@@ -1,6 +1,6 @@
GLOBAL_LIST_EMPTY(TabletMessengers) // a list of all active messengers, similar to GLOB.PDAs (used primarily with ntmessenger.dm)
// This is the base type that does all the hardware stuff.
// This is the base type of computer
// Other types expand it - tablets and laptops are subtypes
// consoles use "procssor" item that is held inside it.
/obj/item/modular_computer
@@ -14,16 +14,20 @@ GLOBAL_LIST_EMPTY(TabletMessengers) // a list of all active messengers, similar
armor = list(MELEE = 0, BULLET = 20, LASER = 20, ENERGY = 100, BOMB = 0, BIO = 0, FIRE = 0, ACID = 0)
light_system = MOVABLE_LIGHT_DIRECTIONAL
///The power cell the computer uses to run on.
var/obj/item/stock_parts/cell/internal_cell = /obj/item/stock_parts/cell
///The ID currently stored in the computer.
var/obj/item/card/id/computer_id_slot
///The disk in this PDA. If set, this will be inserted on Initialize.
var/obj/item/computer_disk/inserted_disk
///The power cell the computer uses to run on.
var/obj/item/stock_parts/cell/internal_cell = /obj/item/stock_parts/cell
///A pAI currently loaded into the modular computer.
var/obj/item/pai_card/inserted_pai
///The amount of storage space the computer starts with.
var/max_capacity = 128
///The amount of storage space we've got filled
var/used_capacity = 0
///List of stored files on this drive. DO NOT MODIFY DIRECTLY!
///List of stored files on this drive. Use `store_file` and `remove_file` instead of modifying directly!
var/list/datum/computer_file/stored_files = list()
///Non-static list of programs the computer should recieve on Initialize.
@@ -35,13 +39,20 @@ GLOBAL_LIST_EMPTY(TabletMessengers) // a list of all active messengers, similar
/datum/computer_file/program/filemanager,
)
///The program currently active on the tablet.
var/datum/computer_file/program/active_program
///Idle programs on background. They still receive process calls but can't be interacted with.
var/list/idle_threads = list()
/// Amount of programs that can be ran at once
var/max_idle_programs = 2
///Flag of the type of device the modular computer is, deciding what types of apps it can run.
var/hardware_flag = NONE
// Options: PROGRAM_ALL | PROGRAM_CONSOLE | PROGRAM_LAPTOP | PROGRAM_TABLET
///Whether the icon state should be bypassed entirely, used for PDAs.
var/bypass_state = FALSE
///The theme, used for the main menu, some hardware config, and file browser apps.
///The theme, used for the main menu and file browser apps.
var/device_theme = "ntos"
///Bool on whether the computer is currently active or not.
@@ -63,12 +74,12 @@ GLOBAL_LIST_EMPTY(TabletMessengers) // a list of all active messengers, similar
///The last recorded amount of power used.
var/last_power_usage = 0
///Power usage when the computer is open (screen is active) and can be interacted with. Remember hardware can use power too.
///Power usage when the computer is open (screen is active) and can be interacted with.
var/base_active_power_usage = 75
///Power usage when the computer is idle and screen is off (currently only applies to laptops)
var/base_idle_power_usage = 5
// Modular computers can run on various devices. Each DEVICE (Laptop, Console, Tablet,..)
// 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.
@@ -77,41 +88,22 @@ GLOBAL_LIST_EMPTY(TabletMessengers) // a list of all active messengers, similar
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/display_overlays = TRUE // If FALSE, don't draw overlays on this device at all
/// List of "connection ports" in this computer and the components with which they are plugged
var/list/all_components = list()
/// Lazy List of extra hardware slots that can be used modularly.
var/list/expansion_bays
/// Number of total expansion bays this computer has available.
var/max_bays = 0
///The w_class (size) hardware it can handle, laptops get extra, computers get more.
var/max_hardware_size = 0
///The full name of the stored ID card's identity. These vars should probably be on the PDA.
var/saved_identification
///The job title of the stored ID card
var/saved_job
///The program currently active on the tablet.
var/datum/computer_file/program/active_program
///Idle programs on background. They still receive process calls but can't be interacted with.
var/list/idle_threads = list()
/// Amount of programs that can be ran at once
var/max_idle_programs = 2
///The 'computer' itself, as an obj. Primarily used for Adjacent() and UI visibility checks, especially for computers.
var/obj/physical
///Amount of steel sheets refunded when disassembling an empty frame of this computer.
var/steel_sheet_cost = 5
///A pAI currently loaded into the modular computer.
var/obj/item/pai_card/inserted_pai
/// Allow people with chunky fingers to use?
var/allow_chunky = FALSE
///If hit by a Clown virus, remaining honks left until it stops.
var/honkvirus_amount = 0
///Whether the PDA can still use NTNet while out of NTNet's reach.
var/long_ranged = FALSE
/// Allow people with chunky fingers to use?
var/allow_chunky = FALSE
///The amount of paper currently stored in the PDA
var/stored_paper = 10
@@ -153,10 +145,6 @@ GLOBAL_LIST_EMPTY(TabletMessengers) // a list of all active messengers, similar
wipe_program(forced = TRUE)
for(var/datum/computer_file/program/idle as anything in idle_threads)
idle.kill_program(TRUE)
for(var/port in all_components)
var/obj/item/computer_hardware/component = all_components[port]
qdel(component)
all_components?.Cut()
//Some components will actually try and interact with this, so let's do it later
QDEL_NULL(soundloop)
QDEL_LIST(stored_files)
@@ -166,6 +154,8 @@ GLOBAL_LIST_EMPTY(TabletMessengers) // a list of all active messengers, similar
QDEL_NULL(inserted_disk)
if(istype(inserted_pai))
QDEL_NULL(inserted_pai)
if(computer_id_slot)
QDEL_NULL(computer_id_slot)
physical = null
return ..()
@@ -201,98 +191,37 @@ GLOBAL_LIST_EMPTY(TabletMessengers) // a list of all active messengers, similar
return internal_cell
/obj/item/modular_computer/AltClick(mob/user)
..()
. = ..()
if(issilicon(user))
return
return FALSE
if(!user.canUseTopic(src, be_close = TRUE))
return FALSE
if(user.canUseTopic(src, be_close = TRUE))
var/obj/item/computer_hardware/card_slot/card_slot2 = all_components[MC_CARD2]
var/obj/item/computer_hardware/card_slot/card_slot = all_components[MC_CARD]
if(RemoveID(user))
return TRUE
if(istype(card_slot) && card_slot.stored_card && card_slot?.try_eject(user))
return TRUE
if(istype(card_slot2) && card_slot2?.stored_card && card_slot2?.try_eject(user))
return TRUE
if(istype(inserted_pai)) // Remove pAI
user.put_in_hands(inserted_pai)
balloon_alert(user, "removed pAI")
inserted_pai = null
return TRUE
if(!istype(src, /obj/item/modular_computer/tablet))
return FALSE
if(istype(inserted_pai)) // Remove pAI
user.put_in_hands(inserted_pai)
balloon_alert(user, "removed pAI")
inserted_pai = null
return TRUE
// Gets IDs/access levels from card slot. Would be useful when/if PDAs would become modular PCs. //guess what
/obj/item/modular_computer/GetAccess()
var/obj/item/computer_hardware/card_slot/card_slot = all_components[MC_CARD]
if(card_slot)
return card_slot.GetAccess()
if(computer_id_slot)
return computer_id_slot.GetAccess()
return ..()
/obj/item/modular_computer/GetID()
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/obj/item/card/id/first_id = card_slot?.GetID()
var/obj/item/card/id/second_id = card_slot2?.GetID()
// We have two IDs, pick the one with the most command accesses, preferring the primary slot.
if(first_id && second_id)
var/first_id_tally = SSid_access.tally_access(first_id, ACCESS_FLAG_COMMAND)
var/second_id_tally = SSid_access.tally_access(second_id, ACCESS_FLAG_COMMAND)
return (first_id_tally >= second_id_tally) ? first_id : second_id
// If we don't have both ID slots filled, pick the one that is filled.
if(first_id)
return first_id
if(second_id)
return second_id
// Otherwise, we have no ID at all.
if(computer_id_slot)
return computer_id_slot
return ..()
/obj/item/modular_computer/get_id_examine_strings(mob/user)
. = ..()
var/obj/item/computer_hardware/card_slot/card_slot2 = all_components[MC_CARD2]
var/obj/item/computer_hardware/card_slot/card_slot = all_components[MC_CARD]
var/obj/item/card/id/id_card1 = card_slot?.GetID()
var/obj/item/card/id/id_card2 = card_slot2?.GetID()
if(id_card1 || id_card2)
if(id_card1 && id_card2)
. += "\The [src] is displaying [id_card1] and [id_card2]."
var/list/id_icons = list()
id_icons += id_card1.get_id_examine_strings(user)
id_icons += id_card2.get_id_examine_strings(user)
. += id_icons.Join(" ")
else if(id_card1)
. += "\The [src] is displaying [id_card1]."
. += id_card1.get_id_examine_strings(user)
else
. += "\The [src] is displaying [id_card2]."
. += id_card2.get_id_examine_strings(user)
/obj/item/modular_computer/RemoveID()
var/obj/item/computer_hardware/card_slot/card_slot2 = all_components[MC_CARD2]
var/obj/item/computer_hardware/card_slot/card_slot = all_components[MC_CARD]
var/removed_id = (card_slot2?.try_eject() || card_slot?.try_eject())
if(removed_id)
if(ishuman(loc))
var/mob/living/carbon/human/human_wearer = loc
if(human_wearer.wear_id == src)
human_wearer.sec_hud_set_ID()
update_slot_icon()
update_appearance()
return removed_id
return ..()
if(computer_id_slot)
. += "\The [src] is displaying [computer_id_slot]."
. += computer_id_slot.get_id_examine_strings(user)
/obj/item/modular_computer/proc/print_text(text_to_print, paper_title = "")
if(!stored_paper)
@@ -306,25 +235,61 @@ GLOBAL_LIST_EMPTY(TabletMessengers) // a list of all active messengers, similar
stored_paper--
return TRUE
/obj/item/modular_computer/InsertID(obj/item/inserting_item)
var/obj/item/computer_hardware/card_slot/card_slot = all_components[MC_CARD]
var/obj/item/computer_hardware/card_slot/card_slot2 = all_components[MC_CARD2]
if(!(card_slot || card_slot2))
/**
* InsertID
* Attempt to insert the ID in either card slot.
* Args:
* inserting_id - the ID being inserted
* user - The person inserting the ID
*/
/obj/item/modular_computer/InsertID(obj/item/card/inserting_id, mob/user)
//all slots taken
if(computer_id_slot)
return FALSE
var/obj/item/card/inserting_id = inserting_item.GetID()
if(!inserting_id)
return FALSE
computer_id_slot = inserting_id
if(user)
if(!user.transferItemToLoc(inserting_id, src))
return FALSE
to_chat(user, span_notice("You insert \the [inserting_id] into the card slot."))
else
inserting_id.forceMove(src)
if((card_slot?.try_insert(inserting_id)) || (card_slot2?.try_insert(inserting_id)))
if(ishuman(loc))
var/mob/living/carbon/human/human_wearer = loc
if(human_wearer.wear_id == src)
human_wearer.sec_hud_set_ID()
update_appearance()
update_slot_icon()
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE)
if(ishuman(loc))
var/mob/living/carbon/human/human_wearer = loc
if(human_wearer.wear_id == src)
human_wearer.sec_hud_set_ID()
update_appearance()
update_slot_icon()
return TRUE
/**
* Removes the ID card from the computer, and puts it in loc's hand if it's a mob
* Args:
* user - The mob trying to remove the ID, if there is one
*/
/obj/item/modular_computer/RemoveID(mob/user)
if(!computer_id_slot)
return ..()
if(user)
if(!issilicon(user) && in_range(src, user))
user.put_in_hands(computer_id_slot)
balloon_alert(user, "removed ID")
to_chat(user, span_notice("You remove the card from the card slot."))
else
computer_id_slot.forceMove(drop_location())
computer_id_slot = null
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE)
if(ishuman(loc))
var/mob/living/carbon/human/human_wearer = loc
if(human_wearer.wear_id == src)
human_wearer.sec_hud_set_ID()
update_slot_icon()
update_appearance()
return TRUE
/obj/item/modular_computer/MouseDrop(obj/over_object, src_location, over_location)
@@ -379,21 +344,12 @@ GLOBAL_LIST_EMPTY(TabletMessengers) // a list of all active messengers, similar
. += "It is upgraded with an experimental long-ranged network capabilities, picking up NTNet frequencies while further away."
. += span_notice("It has [max_capacity] GQ of storage capacity.")
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":""].")
if(computer_id_slot)
if(Adjacent(user))
. += "It has \the [computer_id_slot] card installed in its card slot."
else
. += "It has [multiple_slots ? "two slots" : "a slot"] installed for identification cards."
. += "Its identification card slot is currently occupied."
. += span_info("Alt-click [src] to eject the identification card.")
/obj/item/modular_computer/examine_more(mob/user)
. = ..()
@@ -409,10 +365,7 @@ GLOBAL_LIST_EMPTY(TabletMessengers) // a list of all active messengers, similar
/obj/item/modular_computer/add_context(atom/source, list/context, obj/item/held_item, mob/living/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]
if(card_slot?.stored_card || card_slot2?.stored_card) // IDs get removed first before pAIs
if(computer_id_slot) // ID get removed first before pAIs
context[SCREENTIP_CONTEXT_ALT_LMB] = "Remove ID"
. = CONTEXTUAL_SCREENTIP_SET
else if(inserted_pai)
@@ -450,6 +403,12 @@ GLOBAL_LIST_EMPTY(TabletMessengers) // a list of all active messengers, similar
internal_cell = null
if(enabled && !use_power())
shutdown_computer()
if(computer_id_slot == gone)
computer_id_slot = null
update_slot_icon()
if(ishuman(loc))
var/mob/living/carbon/human/human_wearer = loc
human_wearer.sec_hud_set_ID()
return ..()
// On-click handling. Turns on the computer if it's off and opens the GUI.
@@ -744,13 +703,12 @@ GLOBAL_LIST_EMPTY(TabletMessengers) // a list of all active messengers, similar
/obj/item/modular_computer/attackby(obj/item/attacking_item, mob/user, params)
// Check for ID first
if(isidcard(attacking_item) && InsertID(attacking_item))
if(isidcard(attacking_item) && InsertID(attacking_item, user))
return
// Check for cash next
var/obj/item/computer_hardware/card_slot/card_slot = all_components[MC_CARD]
if(card_slot && iscash(attacking_item))
var/obj/item/card/id/inserted_id = card_slot.GetID()
if(computer_id_slot && iscash(attacking_item))
var/obj/item/card/id/inserted_id = computer_id_slot.GetID()
if(inserted_id)
inserted_id.attackby(attacking_item, user) // If we do, try and put that attacking object in
return
@@ -807,13 +765,6 @@ GLOBAL_LIST_EMPTY(TabletMessengers) // a list of all active messengers, similar
bin.update_appearance()
return
// Insert items into the components
for(var/h in all_components)
var/obj/item/computer_hardware/H = all_components[h]
if(H.try_insert(attacking_item, user))
return
// Insert a data disk
if(istype(attacking_item, /obj/item/computer_disk))
if(!user.transferItemToLoc(attacking_item, src))
@@ -822,48 +773,10 @@ GLOBAL_LIST_EMPTY(TabletMessengers) // a list of all active messengers, similar
playsound(src, 'sound/machines/card_slide.ogg', 50)
return
// Insert new hardware
if(istype(attacking_item, /obj/item/computer_hardware))
if(install_component(attacking_item, user))
playsound(src, 'sound/machines/card_slide.ogg', 50)
return
return ..()
/obj/item/modular_computer/screwdriver_act(mob/user, obj/item/tool)
. = ..()
if((resistance_flags & INDESTRUCTIBLE) || (flags_1 & NODECONSTRUCT_1))
return
if(!length(all_components))
balloon_alert(user, "no components installed!")
return
var/list/component_names = list()
for(var/h in all_components)
var/obj/item/computer_hardware/H = all_components[h]
component_names.Add(H.name)
var/choice = tgui_input_list(user, "Component to uninstall", "Computer maintenance", sort_list(component_names))
if(isnull(choice))
if(internal_cell)
user.put_in_hands(internal_cell)
to_chat(user, span_notice("You detach \the [internal_cell] from \the [src]."))
return TOOL_ACT_TOOLTYPE_SUCCESS
if(!Adjacent(user))
return
var/obj/item/computer_hardware/H = find_hardware_by_name(choice)
if(!H)
return TOOL_ACT_TOOLTYPE_SUCCESS
tool.play_tool_sound(src, user, 20, volume=20)
uninstall_component(H, user)
return TOOL_ACT_TOOLTYPE_SUCCESS
/obj/item/modular_computer/wrench_act(mob/living/user, obj/item/tool)
. = ..()
if(length(all_components))
balloon_alert(user, "remove the other components!")
return TOOL_ACT_TOOLTYPE_SUCCESS
tool.play_tool_sound(src, user, 20, volume=20)
new /obj/item/stack/sheet/iron(get_turf(loc), steel_sheet_cost)
user.balloon_alert(user, "disassembled")
@@ -871,7 +784,6 @@ GLOBAL_LIST_EMPTY(TabletMessengers) // a list of all active messengers, similar
qdel(src)
return TOOL_ACT_TOOLTYPE_SUCCESS
/obj/item/modular_computer/welder_act(mob/living/user, obj/item/tool)
. = ..()
if(atom_integrity == max_integrity)
@@ -889,6 +801,16 @@ GLOBAL_LIST_EMPTY(TabletMessengers) // a list of all active messengers, similar
update_appearance()
return TOOL_ACT_TOOLTYPE_SUCCESS
/obj/item/modular_computer/deconstruct(disassembled = TRUE)
break_apart()
return ..()
/obj/item/modular_computer/proc/break_apart()
if(!(flags_1 & NODECONSTRUCT_1))
physical.visible_message(span_notice("\The [src] breaks apart!"))
var/turf/newloc = get_turf(src)
new /obj/item/stack/sheet/iron(newloc, round(steel_sheet_cost / 2))
relay_qdel()
// Used by processor to relay qdel() to machinery type.
/obj/item/modular_computer/proc/relay_qdel()
@@ -1,71 +0,0 @@
/obj/item/modular_computer/proc/can_install_component(obj/item/computer_hardware/try_install, mob/living/user = null)
if(!try_install.can_install(src, user))
return FALSE
if(try_install.w_class > max_hardware_size)
to_chat(user, span_warning("This component is too large for \the [src]!"))
return FALSE
if(try_install.expansion_hw)
if(LAZYLEN(expansion_bays) >= max_bays)
to_chat(user, span_warning("All of the computer's expansion bays are filled."))
return FALSE
if(LAZYACCESS(expansion_bays, try_install.device_type))
to_chat(user, span_warning("The computer immediately ejects /the [try_install] and flashes an error: \"Hardware Address Conflict\"."))
return FALSE
if(all_components[try_install.device_type])
to_chat(user, span_warning("This computer's hardware slot is already occupied by \the [all_components[try_install.device_type]]."))
return FALSE
return TRUE
/// Installs component.
/obj/item/modular_computer/proc/install_component(obj/item/computer_hardware/install, mob/living/user = null)
if(!can_install_component(install, user))
return FALSE
if(user && !user.transferItemToLoc(install, src))
return FALSE
if(install.expansion_hw)
LAZYSET(expansion_bays, install.device_type, install)
all_components[install.device_type] = install
to_chat(user, span_notice("You install \the [install] into \the [src]."))
install.holder = src
install.forceMove(src)
install.on_install(src, user)
/// Uninstalls component.
/obj/item/modular_computer/proc/uninstall_component(obj/item/computer_hardware/yeet, mob/living/user = null)
if(yeet.holder != src) // Not our component at all.
return FALSE
to_chat(user, span_notice("You remove \the [yeet] from \the [src]."))
yeet.forceMove(get_turf(src))
forget_component(yeet)
yeet.on_remove(src, user)
if(enabled && !use_power())
shutdown_computer()
update_appearance()
return TRUE
/// This isn't the "uninstall fully" proc, it just makes the computer lose all its references to the component
/obj/item/modular_computer/proc/forget_component(obj/item/computer_hardware/wipe_memory)
if(wipe_memory.holder != src)
return FALSE
if(wipe_memory.expansion_hw)
LAZYREMOVE(expansion_bays, wipe_memory.device_type)
all_components.Remove(wipe_memory.device_type)
wipe_memory.holder = null
/// 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)
for(var/i in all_components)
var/obj/component = all_components[i]
if(component.name == name)
return component
return null
@@ -1,32 +0,0 @@
/obj/item/modular_computer/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1)
. = ..()
var/component_probability = min(50, max(damage_amount*0.1, 1 - atom_integrity/max_integrity))
switch(damage_flag)
if(BULLET)
component_probability = damage_amount * 0.5
if(LASER)
component_probability = damage_amount * 0.66
if(component_probability)
for(var/I in all_components)
var/obj/item/computer_hardware/H = all_components[I]
if(prob(component_probability))
H.take_damage(round(damage_amount*0.5), damage_type, damage_flag, 0)
/obj/item/modular_computer/deconstruct(disassembled = TRUE)
break_apart()
return ..()
/obj/item/modular_computer/proc/break_apart()
if(!(flags_1 & NODECONSTRUCT_1))
physical.visible_message(span_notice("\The [src] breaks apart!"))
var/turf/newloc = get_turf(src)
new /obj/item/stack/sheet/iron(newloc, round(steel_sheet_cost/2))
for(var/C in all_components)
var/obj/item/computer_hardware/H = all_components[C]
if(QDELETED(H))
continue
uninstall_component(H)
H.forceMove(newloc)
if(prob(25))
H.take_damage(rand(10,30), BRUTE, 0, 0)
relay_qdel()
@@ -34,10 +34,6 @@
/obj/item/modular_computer/proc/handle_power(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)
if(H.enabled)
power_usage += H.power_usage
if(use_power(power_usage))
last_power_usage = power_usage
return TRUE
@@ -59,10 +59,7 @@
data["device_theme"] = device_theme
data["login"] = list()
var/obj/item/computer_hardware/card_slot/cardholder = all_components[MC_CARD]
data["cardholder"] = !!cardholder
if(cardholder)
if(computer_id_slot)
var/stored_name = saved_identification
var/stored_title = saved_job
if(!stored_name)
@@ -74,8 +71,8 @@
IDJob = saved_job,
)
data["proposed_login"] = list(
IDName = cardholder.current_identification,
IDJob = cardholder.current_job,
IDName = computer_id_slot.registered_name,
IDJob = computer_id_slot.assignment,
)
data["removable_media"] = list()
@@ -84,9 +81,6 @@
var/datum/computer_file/program/ai_restorer/airestore_app = locate() in 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()
for(var/datum/computer_file/program/P in stored_files)
@@ -182,28 +176,14 @@
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]
if(!cardholder)
return
if(cardholder.try_eject(user))
playsound(src, 'sound/machines/card_slide.ogg', 50)
if("secondary RFID card")
var/obj/item/computer_hardware/card_slot/cardholder = all_components[MC_CARD2]
if(!cardholder)
return
if(cardholder.try_eject(user))
if(RemoveID())
playsound(src, 'sound/machines/card_slide.ogg', 50)
if("PC_Imprint_ID")
var/obj/item/computer_hardware/card_slot/cardholder = all_components[MC_CARD]
if(!cardholder)
return
saved_identification = cardholder.current_identification
saved_job = cardholder.current_job
saved_identification = computer_id_slot.registered_name
saved_job = computer_id_slot.assignment
UpdateDisplay()
playsound(src, 'sound/machines/terminal_processing.ogg', 15, TRUE)
if("PC_Pai_Interact")
switch(params["option"])
if("eject")
@@ -10,10 +10,8 @@
display_overlays = FALSE
hardware_flag = PROGRAM_LAPTOP
max_hardware_size = 2
max_idle_programs = 3
w_class = WEIGHT_CLASS_NORMAL
max_bays = 4
// No running around with open laptops in hands.
item_flags = SLOWS_WHILE_IN_HAND
@@ -1,5 +1,5 @@
// Held by /obj/machinery/modular_computer to reduce amount of copy-pasted code.
//TODO: REFACTOR THIS SPAGHETTI CODE, MAKE IT A COMPUTER_HARDWARE COMPONENT OR REMOVE IT
//TODO: REFACTOR THIS SPAGHETTI CODE
/obj/item/modular_computer/processor
name = "processing unit"
desc = "An advanced computer." //modular PCs examine us
@@ -8,7 +8,6 @@
icon_state_unpowered = null
icon_state_menu = null
hardware_flag = 0
max_bays = 4
///The modular computer MACHINE that hosts us.
var/obj/machinery/modular_computer/machinery_computer
@@ -27,7 +26,6 @@
machinery_computer.cpu = src
internal_cell = machinery_computer.internal_cell
hardware_flag = machinery_computer.hardware_flag
max_hardware_size = machinery_computer.max_hardware_size
steel_sheet_cost = machinery_computer.steel_sheet_cost
max_idle_programs = machinery_computer.max_idle_programs
update_integrity(machinery_computer.get_integrity())
@@ -13,10 +13,6 @@
/datum/computer_file/program/budgetorders,
)
/obj/item/modular_computer/tablet/pda/heads/Initialize(mapload)
. = ..()
install_component(new /obj/item/computer_hardware/card_slot/secondary)
/obj/item/modular_computer/tablet/pda/heads/captain
name = "captain PDA"
greyscale_config = /datum/greyscale_config/tablet/captain
@@ -11,10 +11,8 @@
base_icon_state = "tablet"
worn_icon_state = "tablet"
hardware_flag = PROGRAM_TABLET
max_hardware_size = 1
max_idle_programs = 2
w_class = WEIGHT_CLASS_SMALL
max_bays = 3
steel_sheet_cost = 2
slot_flags = ITEM_SLOT_ID | ITEM_SLOT_BELT
has_light = TRUE //LED flashlight!
@@ -166,8 +164,6 @@
inserted_item = null
update_appearance()
playsound(src, 'sound/machines/pda_button2.ogg', 50, TRUE)
else
balloon_alert(user, "nothing to remove!")
// Tablet 'splosion..
@@ -412,8 +408,7 @@
/obj/item/modular_computer/tablet/pda/update_overlays()
. = ..()
var/obj/item/computer_hardware/card_slot/card = all_components[MC_CARD]
if(card?.stored_card)
if(computer_id_slot)
. += mutable_appearance(initial(icon), "id_overlay")
if(light_on)
. += mutable_appearance(initial(icon), "light_overlay")
@@ -421,7 +416,3 @@
/obj/item/modular_computer/tablet/pda/attack_ai(mob/user)
to_chat(user, span_notice("It doesn't feel right to snoop around like that..."))
return // we don't want ais or cyborgs using a private role tablet
/obj/item/modular_computer/tablet/pda/Initialize(mapload)
. = ..()
install_component(new /obj/item/computer_hardware/card_slot)
@@ -1,6 +1,4 @@
/obj/machinery/modular_computer/console/preset
// Can be changed to give devices specific hardware
var/_has_second_id_slot = FALSE
///List of programs the computer starts with, given on Initialize.
var/list/datum/computer_file/starting_programs = list()
@@ -9,9 +7,6 @@
if(!cpu)
return
cpu.install_component(new /obj/item/computer_hardware/card_slot)
if(_has_second_id_slot)
cpu.install_component(new /obj/item/computer_hardware/card_slot/secondary)
for(var/programs in starting_programs)
var/datum/computer_file/program/program_type = new programs
cpu.store_file(program_type)
@@ -32,7 +27,6 @@
console_department = "Research"
name = "research director's console"
desc = "A stationary computer. This one comes preloaded with research programs."
_has_second_id_slot = TRUE
starting_programs = list(
/datum/computer_file/program/ntnetmonitor,
/datum/computer_file/program/chatclient,
@@ -46,7 +40,6 @@
console_department = "Command"
name = "command console"
desc = "A stationary computer. This one comes preloaded with command programs."
_has_second_id_slot = TRUE
starting_programs = list(
/datum/computer_file/program/chatclient,
/datum/computer_file/program/card_mod,
@@ -57,7 +50,6 @@
console_department = "Identification"
name = "identification console"
desc = "A stationary computer. This one comes preloaded with identification modification programs."
_has_second_id_slot = TRUE
starting_programs = list(
/datum/computer_file/program/chatclient,
/datum/computer_file/program/card_mod,
@@ -29,13 +29,11 @@
var/screen_icon_state_menu = "menu"
///Icon state overlay when the computer is powered, but not 'switched on'.
var/screen_icon_screensaver = "standby"
///Maximal hardware size. Currently, tablets have 1, laptops 2 and consoles 3. Limits what hardware types can be installed.
var/max_hardware_size = 0
///Amount of steel sheets refunded when disassembling an empty frame of this computer.
var/steel_sheet_cost = 10
///Light luminosity when turned on
var/light_strength = 0
///Power usage when the computer is open (screen is active) and can be interacted with. Remember hardware can use power too.
///Power usage when the computer is open (screen is active) and can be interacted with.
var/base_active_power_usage = 100
///Power usage when the computer is idle and screen is off (currently only applies to laptops)
var/base_idle_power_usage = 10
@@ -10,7 +10,6 @@
density = TRUE
base_idle_power_usage = 100
base_active_power_usage = 500
max_hardware_size = 4
steel_sheet_cost = 10
light_strength = 2
max_integrity = 300
@@ -80,7 +80,8 @@
/datum/computer_file/program/proc/tap(atom/A, mob/living/user, params)
return FALSE
/datum/computer_file/program/proc/is_supported_by_hardware(hardware_flag = 0, loud = 0, mob/user = null)
///Makes sure a program can run on this hardware (for apps limited to tablets/computers/laptops)
/datum/computer_file/program/proc/is_supported_by_hardware(hardware_flag = NONE, loud = FALSE, mob/user)
if(!(hardware_flag & usage_flags))
if(loud && computer && user)
to_chat(user, span_danger("\The [computer] flashes a \"Hardware Error - Incompatible software\" warning."))
@@ -123,10 +124,8 @@
if(!length(access))
var/obj/item/card/id/accesscard
var/obj/item/computer_hardware/card_slot/card_slot
if(computer)
card_slot = computer.all_components[MC_CARD]
accesscard = card_slot?.GetID()
accesscard = computer.computer_id_slot?.GetID()
if(!accesscard)
if(loud)
@@ -165,10 +164,7 @@
SHOULD_CALL_PARENT(TRUE)
if(can_run(user, 1))
if(requires_ntnet)
var/obj/item/card/id/ID
var/obj/item/computer_hardware/card_slot/card_holder = computer.all_components[MC_CARD]
if(card_holder)
ID = card_holder.GetID()
var/obj/item/card/id/ID = computer.computer_id_slot?.GetID()
generate_network_log("Connection opened -- Program ID: [filename] User:[ID?"[ID.registered_name]":"None"]")
program_state = PROGRAM_STATE_ACTIVE
return TRUE
@@ -201,10 +197,7 @@
if(src in computer.idle_threads)
computer.idle_threads.Remove(src)
if(requires_ntnet)
var/obj/item/card/id/ID
var/obj/item/computer_hardware/card_slot/card_holder = computer.all_components[MC_CARD]
if(card_holder)
ID = card_holder.GetID()
var/obj/item/card/id/ID = computer.computer_id_slot?.GetID()
generate_network_log("Connection closed -- Program ID: [filename] User:[ID ? "[ID.registered_name]" : "None"]")
return TRUE
@@ -1,10 +1,6 @@
// Events are sent to the program by the computer.
// Always include a parent call when overriding an event.
// Called when the ID card is removed from computer. ID is removed AFTER this proc.
/datum/computer_file/program/proc/event_idremoved(background)
return
// 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(forced = TRUE)
@@ -150,7 +150,7 @@
return TRUE
if("Dispense_Tickets")
if(computer.stored_paper <= 0)
to_chat(usr, span_notice("Hardware error: Printer is out of paper."))
to_chat(usr, span_notice("Printer is out of paper."))
return
else
computer.visible_message(span_notice("\The [computer] prints out paper."))
@@ -22,7 +22,6 @@
var/list/data = get_header_data()
var/list/formatted_requests = list()
var/list/formatted_applicants = list()
var/obj/item/computer_hardware/card_slot/card_slot = computer.all_components[MC_CARD]
if(current_user)
data["user"] = list()
data["user"]["name"] = current_user.account_holder
@@ -40,8 +39,8 @@
if(!networked)
GLOB.allbountyboards += computer
networked = TRUE
if(card_slot && card_slot.stored_card && card_slot.stored_card.registered_account)
current_user = card_slot.stored_card.registered_account
if(computer.computer_id_slot)
current_user = computer.computer_id_slot?.registered_account
for(var/i in GLOB.request_list)
if(!i)
continue
@@ -50,11 +50,7 @@
//Aquire access from the inserted ID card.
if(!length(access))
var/obj/item/card/id/D
var/obj/item/computer_hardware/card_slot/card_slot
if(computer)
card_slot = computer.all_components[MC_CARD]
D = card_slot?.GetID()
var/obj/item/card/id/D = computer?.computer_id_slot?.GetID()
if(!D)
return FALSE
access = D.GetAccess()
@@ -70,8 +66,7 @@
data["location"] = SSshuttle.supply.getStatusText()
data["department"] = "Cargo"
var/datum/bank_account/buyer = SSeconomy.get_dep_account(cargo_account)
var/obj/item/computer_hardware/card_slot/card_slot = computer.all_components[MC_CARD]
var/obj/item/card/id/id_card = card_slot?.GetID()
var/obj/item/card/id/id_card = computer.computer_id_slot?.GetID()
if(id_card?.registered_account)
if((ACCESS_COMMAND in id_card.access))
requestonly = FALSE
@@ -150,9 +145,9 @@
return data
/datum/computer_file/program/budgetorders/ui_act(action, params, datum/tgui/ui)
if(..())
. = ..()
if(.)
return
var/obj/item/computer_hardware/card_slot/card_slot = computer.all_components[MC_CARD]
switch(action)
if("send")
if(!SSshuttle.supply.canMove())
@@ -224,7 +219,7 @@
return
var/reason = ""
if((requestonly && !self_paid) || !(card_slot?.GetID()))
if((requestonly && !self_paid) || !(computer.computer_id_slot?.GetID()))
reason = tgui_input_text(usr, "Reason", name)
if(isnull(reason) || ..())
return
@@ -235,13 +230,13 @@
return
if(!requestonly && !self_paid && ishuman(usr) && !account)
var/obj/item/card/id/id_card = card_slot?.GetID()
var/obj/item/card/id/id_card = computer.computer_id_slot?.GetID()
account = SSeconomy.get_dep_account(id_card?.registered_account?.account_job.paycheck_department)
var/turf/T = get_turf(src)
var/datum/supply_order/SO = new(pack, name, rank, ckey, reason, account)
SO.generateRequisition(T)
if((requestonly && !self_paid) || !(card_slot?.GetID()))
if((requestonly && !self_paid) || !(computer.computer_id_slot?.GetID()))
SSshuttle.request_list += SO
else
SSshuttle.shopping_list += SO
@@ -262,7 +257,7 @@
var/id = text2num(params["id"])
for(var/datum/supply_order/SO in SSshuttle.request_list)
if(SO.id == id)
var/obj/item/card/id/id_card = card_slot?.GetID()
var/obj/item/card/id/id_card = computer.computer_id_slot?.GetID()
if(id_card && id_card?.registered_account)
SO.paying_account = SSeconomy.get_dep_account(id_card?.registered_account?.account_job.paycheck_department)
SSshuttle.request_list -= SO
@@ -35,10 +35,10 @@
* compared to the access on the supplied ID card.
* Arguments:
* * user - Program's user.
* * id_card - The ID card to attempt to authenticate under.
* * auth_card - The ID card to attempt to authenticate under.
*/
/datum/computer_file/program/card_mod/proc/authenticate(mob/user, obj/item/card/id/id_card)
if(!id_card)
/datum/computer_file/program/card_mod/proc/authenticate(mob/user, obj/item/card/id/auth_card)
if(!auth_card)
return
region_access.Cut()
@@ -46,10 +46,10 @@
job_templates.Cut()
// If the program isn't locked to a specific department or is_centcom and we have ACCESS_CHANGE_IDS in our auth card, we're not minor.
if((!target_dept || is_centcom) && (ACCESS_CHANGE_IDS in id_card.access))
if((!target_dept || is_centcom) && (ACCESS_CHANGE_IDS in auth_card.access))
minor = FALSE
authenticated_card = "[id_card.name]"
authenticated_user = id_card.registered_name ? id_card.registered_name : "Unknown"
authenticated_card = "[auth_card.name]"
authenticated_user = auth_card.registered_name ? auth_card.registered_name : "Unknown"
job_templates = is_centcom ? SSid_access.centcom_job_templates.Copy() : SSid_access.station_job_templates.Copy()
valid_access = is_centcom ? SSid_access.get_region_access_list(list(REGION_CENTCOM)) : SSid_access.get_region_access_list(list(REGION_ALL_STATION))
update_static_data(user)
@@ -60,14 +60,14 @@
for(var/access_as_text in managers)
var/list/info = managers[access_as_text]
var/access = access_as_text
if((access in id_card.access) && ((target_dept in info["regions"]) || !target_dept))
if((access in auth_card.access) && ((target_dept in info["regions"]) || !target_dept))
region_access |= info["regions"]
job_templates |= info["templates"]
if(length(region_access))
minor = TRUE
valid_access |= SSid_access.get_region_access_list(region_access)
authenticated_card = "[id_card.name] \[LIMITED ACCESS\]"
authenticated_card = "[auth_card.name] \[LIMITED ACCESS\]"
update_static_data(user)
return TRUE
@@ -78,25 +78,16 @@
if(.)
return
var/obj/item/computer_hardware/card_slot/card_slot
var/obj/item/computer_hardware/card_slot/card_slot2
if(computer)
card_slot = computer.all_components[MC_CARD]
card_slot2 = computer.all_components[MC_CARD2]
if(!card_slot || !card_slot2)
return
var/mob/user = usr
var/obj/item/card/id/user_id_card = card_slot.stored_card
var/obj/item/card/id/target_id_card = card_slot2.stored_card
var/obj/item/card/id/inserted_auth_card = computer.computer_id_slot
switch(action)
// Log in.
if("PRG_authenticate")
if(!computer || !user_id_card)
if(!computer || !inserted_auth_card)
playsound(computer, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE)
return TRUE
if(authenticate(user, user_id_card))
if(authenticate(user, inserted_auth_card))
playsound(computer, 'sound/machines/terminal_on.ogg', 50, FALSE)
return TRUE
// Log out.
@@ -113,19 +104,19 @@
return TRUE
var/contents = {"<h4>Access Report</h4>
<u>Prepared By:</u> [authenticated_user]<br>
<u>For:</u> [target_id_card.registered_name ? target_id_card.registered_name : "Unregistered"]<br>
<u>For:</u> [inserted_auth_card.registered_name ? inserted_auth_card.registered_name : "Unregistered"]<br>
<hr>
<u>Assignment:</u> [target_id_card.assignment]<br>
<u>Assignment:</u> [inserted_auth_card.assignment]<br>
<u>Access:</u><br>
"}
var/list/known_access_rights = SSid_access.get_region_access_list(list(REGION_ALL_STATION))
for(var/A in target_id_card.access)
for(var/A in inserted_auth_card.access)
if(A in known_access_rights)
contents += " [SSid_access.get_access_desc(A)]"
contents += " [SSid_access.get_access_desc(A)]"
if(!computer.print_text(contents, "access report - [target_id_card.registered_name ? target_id_card.registered_name : "Unregistered"]"))
to_chat(usr, span_notice("Hardware error: Printer was unable to print the file. It may be out of paper."))
if(!computer.print_text(contents, "access report - [inserted_auth_card.registered_name ? inserted_auth_card.registered_name : "Unregistered"]"))
to_chat(usr, span_notice("Printer is out of paper."))
return TRUE
else
playsound(computer, 'sound/machines/terminal_on.ogg', 50, FALSE)
@@ -133,59 +124,55 @@
return TRUE
// Eject the ID used to log on to the ID app.
if("PRG_ejectauthid")
if(!computer || !card_slot)
return TRUE
if(user_id_card)
return card_slot.try_eject(user)
if(inserted_auth_card)
return computer.RemoveID(usr)
else
var/obj/item/I = user.get_active_held_item()
if(isidcard(I))
return card_slot.try_insert(I, user)
return computer.InsertID(I, user)
// Eject the ID being modified.
if("PRG_ejectmodid")
if(!computer || !card_slot2)
return TRUE
if(target_id_card)
GLOB.data_core.manifest_modify(target_id_card.registered_name, target_id_card.assignment, target_id_card.get_trim_assignment())
return card_slot2.try_eject(user)
if(inserted_auth_card)
GLOB.data_core.manifest_modify(inserted_auth_card.registered_name, inserted_auth_card.assignment, inserted_auth_card.get_trim_assignment())
return computer.RemoveID(usr)
else
var/obj/item/I = user.get_active_held_item()
if(isidcard(I))
return card_slot2.try_insert(I, user)
return computer.InsertID(I, user)
return TRUE
// Used to fire someone. Wipes all access from their card and modifies their assignment.
if("PRG_terminate")
if(!computer || !authenticated_card)
return TRUE
if(minor)
if(!(target_id_card.trim?.type in job_templates))
if(!(inserted_auth_card.trim?.type in job_templates))
to_chat(usr, span_notice("Software error: You do not have the necessary permissions to demote this card."))
return TRUE
// Set the new assignment then remove the trim.
target_id_card.assignment = is_centcom ? "Fired" : "Demoted"
SSid_access.remove_trim_from_card(target_id_card)
inserted_auth_card.assignment = is_centcom ? "Fired" : "Demoted"
SSid_access.remove_trim_from_card(inserted_auth_card)
playsound(computer, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE)
return TRUE
// Change ID card assigned name.
if("PRG_edit")
if(!computer || !authenticated_card || !target_id_card)
if(!computer || !authenticated_card || !inserted_auth_card)
return TRUE
var/old_name = target_id_card.registered_name
var/old_name = inserted_auth_card.registered_name
// Sanitize the name first. We're not using the full sanitize_name proc as ID cards can have a wider variety of things on them that
// would not pass as a formal character name, but would still be valid on an ID card created by a player.
var/new_name = sanitize(params["name"])
if(!new_name)
target_id_card.registered_name = null
inserted_auth_card.registered_name = null
playsound(computer, SFX_TERMINAL_TYPE, 50, FALSE)
target_id_card.update_label()
inserted_auth_card.update_label()
// We had a name before and now we have no name, so this will unassign the card and we update the icon.
if(old_name)
target_id_card.update_icon()
inserted_auth_card.update_icon()
return TRUE
// However, we are going to reject bad names overall including names with invalid characters in them, while allowing numbers.
@@ -195,63 +182,63 @@
to_chat(usr, span_notice("Software error: The ID card rejected the new name as it contains prohibited characters."))
return TRUE
target_id_card.registered_name = new_name
inserted_auth_card.registered_name = new_name
playsound(computer, SFX_TERMINAL_TYPE, 50, FALSE)
target_id_card.update_label()
inserted_auth_card.update_label()
// Card wasn't assigned before and now it is, so update the icon accordingly.
if(!old_name)
target_id_card.update_icon()
inserted_auth_card.update_icon()
return TRUE
// Change age
if("PRG_age")
if(!computer || !authenticated_card || !target_id_card)
if(!computer || !authenticated_card || !inserted_auth_card)
return TRUE
var/new_age = params["id_age"]
if(!isnum(new_age))
stack_trace("[key_name(usr)] ([usr]) attempted to set invalid age \[[new_age]\] to [target_id_card]")
stack_trace("[key_name(usr)] ([usr]) attempted to set invalid age \[[new_age]\] to [inserted_auth_card]")
return TRUE
target_id_card.registered_age = new_age
inserted_auth_card.registered_age = new_age
playsound(computer, SFX_TERMINAL_TYPE, 50, FALSE)
return TRUE
// Change assignment
if("PRG_assign")
if(!computer || !authenticated_card || !target_id_card)
if(!computer || !authenticated_card || !inserted_auth_card)
return TRUE
var/new_asignment = sanitize(params["assignment"])
target_id_card.assignment = new_asignment
inserted_auth_card.assignment = new_asignment
playsound(computer, SFX_TERMINAL_TYPE, 50, FALSE)
target_id_card.update_label()
inserted_auth_card.update_label()
return TRUE
// Add/remove access.
if("PRG_access")
if(!computer || !authenticated_card || !target_id_card)
if(!computer || !authenticated_card || !inserted_auth_card)
return TRUE
playsound(computer, SFX_TERMINAL_TYPE, 50, FALSE)
var/access_type = params["access_target"]
var/try_wildcard = params["access_wildcard"]
if(!(access_type in valid_access))
stack_trace("[key_name(usr)] ([usr]) attempted to add invalid access \[[access_type]\] to [target_id_card]")
stack_trace("[key_name(usr)] ([usr]) attempted to add invalid access \[[access_type]\] to [inserted_auth_card]")
return TRUE
if(access_type in target_id_card.access)
target_id_card.remove_access(list(access_type))
LOG_ID_ACCESS_CHANGE(user, target_id_card, "removed [SSid_access.get_access_desc(access_type)]")
if(access_type in inserted_auth_card.access)
inserted_auth_card.remove_access(list(access_type))
LOG_ID_ACCESS_CHANGE(user, inserted_auth_card, "removed [SSid_access.get_access_desc(access_type)]")
return TRUE
if(!target_id_card.add_access(list(access_type), try_wildcard))
if(!inserted_auth_card.add_access(list(access_type), try_wildcard))
to_chat(usr, span_notice("ID error: ID card rejected your attempted access modification."))
LOG_ID_ACCESS_CHANGE(user, target_id_card, "failed to add [SSid_access.get_access_desc(access_type)][try_wildcard ? " with wildcard [try_wildcard]" : ""]")
LOG_ID_ACCESS_CHANGE(user, inserted_auth_card, "failed to add [SSid_access.get_access_desc(access_type)][try_wildcard ? " with wildcard [try_wildcard]" : ""]")
return TRUE
if(access_type in ACCESS_ALERT_ADMINS)
message_admins("[ADMIN_LOOKUPFLW(user)] just added [SSid_access.get_access_desc(access_type)] to an ID card [ADMIN_VV(target_id_card)] [(target_id_card.registered_name) ? "belonging to [target_id_card.registered_name]." : "with no registered name."]")
LOG_ID_ACCESS_CHANGE(user, target_id_card, "added [SSid_access.get_access_desc(access_type)]")
message_admins("[ADMIN_LOOKUPFLW(user)] just added [SSid_access.get_access_desc(access_type)] to an ID card [ADMIN_VV(inserted_auth_card)] [(inserted_auth_card.registered_name) ? "belonging to [inserted_auth_card.registered_name]." : "with no registered name."]")
LOG_ID_ACCESS_CHANGE(user, inserted_auth_card, "added [SSid_access.get_access_desc(access_type)]")
return TRUE
// Apply template to ID card.
if("PRG_template")
if(!computer || !authenticated_card || !target_id_card)
if(!computer || !authenticated_card || !inserted_auth_card)
return TRUE
playsound(computer, SFX_TERMINAL_TYPE, 50, FALSE)
@@ -265,10 +252,10 @@
if(trim.assignment != template_name)
continue
SSid_access.add_trim_access_to_card(target_id_card, trim_path)
SSid_access.add_trim_access_to_card(inserted_auth_card, trim_path)
return TRUE
stack_trace("[key_name(usr)] ([usr]) attempted to apply invalid template \[[template_name]\] to [target_id_card]")
stack_trace("[key_name(usr)] ([usr]) attempted to apply invalid template \[[template_name]\] to [inserted_auth_card]")
return TRUE
@@ -302,39 +289,21 @@
/datum/computer_file/program/card_mod/ui_data(mob/user)
var/list/data = get_header_data()
data["station_name"] = station_name()
var/obj/item/computer_hardware/card_slot/card_slot
var/obj/item/computer_hardware/card_slot/card_slot2
if(computer)
card_slot = computer.all_components[MC_CARD]
card_slot2 = computer.all_components[MC_CARD2]
data["have_auth_card"] = !!(card_slot)
data["have_id_slot"] = !!(card_slot2)
else
data["have_id_slot"] = FALSE
if(!card_slot2)
return data //We're just gonna error out on the js side at this point anyway
var/obj/item/card/id/auth_card = card_slot.stored_card
data["authIDName"] = auth_card ? auth_card.name : "-----"
var/obj/item/card/id/inserted_id = computer.computer_id_slot
data["authIDName"] = inserted_id ? inserted_id.name : "-----"
data["authenticatedUser"] = authenticated_card
var/obj/item/card/id/id_card = card_slot2.stored_card
data["has_id"] = !!id_card
data["id_name"] = id_card ? id_card.name : "-----"
if(id_card)
data["id_rank"] = id_card.assignment ? id_card.assignment : "Unassigned"
data["id_owner"] = id_card.registered_name ? id_card.registered_name : "-----"
data["access_on_card"] = id_card.access
data["wildcardSlots"] = id_card.wildcard_slots
data["id_age"] = id_card.registered_age
data["has_id"] = !!inserted_id
data["id_name"] = inserted_id ? inserted_id.name : "-----"
if(inserted_id)
data["id_rank"] = inserted_id.assignment ? inserted_id.assignment : "Unassigned"
data["id_owner"] = inserted_id.registered_name ? inserted_id.registered_name : "-----"
data["access_on_card"] = inserted_id.access
data["wildcardSlots"] = inserted_id.wildcard_slots
data["id_age"] = inserted_id.registered_age
if(id_card.trim)
var/datum/id_trim/card_trim = id_card.trim
if(inserted_id.trim)
var/datum/id_trim/card_trim = inserted_id.trim
data["hasTrim"] = TRUE
data["trimAssignment"] = card_trim.assignment ? card_trim.assignment : ""
data["trimAccess"] = card_trim.access ? card_trim.access : list()
@@ -19,11 +19,9 @@
/datum/computer_file/program/shipping/ui_data(mob/user)
var/list/data = get_header_data()
var/obj/item/computer_hardware/card_slot/card_slot = computer.all_components[MC_CARD]
var/obj/item/card/id/id_card = card_slot ? card_slot.stored_card : null
data["has_id_slot"] = !!card_slot
data["has_id_slot"] = !!computer.computer_id_slot
data["paperamt"] = "[computer.stored_paper] / [computer.max_paper]"
data["card_owner"] = card_slot?.stored_card ? id_card.registered_name : "No Card Inserted."
data["card_owner"] = computer.computer_id_slot || "No Card Inserted."
data["current_user"] = payments_acc ? payments_acc.account_holder : null
data["barcode_split"] = cut_multiplier * 100
return data
@@ -35,23 +33,17 @@
if(!computer)
return
// Get components
var/obj/item/computer_hardware/card_slot/card_slot = computer.all_components[MC_CARD]
var/obj/item/card/id/id_card = card_slot ? card_slot.stored_card : null
if(!card_slot) //We need both to successfully use this app.
if(!computer.computer_id_slot) //We need an ID to successfully run
return
switch(action)
if("ejectid")
if(id_card)
card_slot.try_eject(usr, TRUE)
computer.RemoveID(usr)
if("selectid")
if(!id_card)
return
if(!id_card.registered_account)
if(!computer.computer_id_slot.registered_account)
playsound(get_turf(ui_host()), 'sound/machines/buzz-sigh.ogg', 50, TRUE, -1)
return
payments_acc = id_card.registered_account
payments_acc = computer.computer_id_slot.registered_account
playsound(get_turf(ui_host()), 'sound/machines/ping.ogg', 50, TRUE, -1)
if("resetid")
payments_acc = null
@@ -60,7 +52,7 @@
cut_multiplier = potential_cut ? clamp(round(potential_cut/100, cut_min), cut_min, cut_max) : initial(cut_multiplier)
if("print")
if(computer.stored_paper <= 0)
to_chat(usr, span_notice("Hardware error: Printer is out of paper."))
to_chat(usr, span_notice("Printer is out of paper."))
return
if(!payments_acc)
to_chat(usr, span_notice("Software error: Please set a current user first."))
@@ -17,7 +17,7 @@
/datum/computer_file/program/computerconfig/ui_data(mob/user)
// No computer connection, we can't get data from that.
if(!computer)
return 0
return FALSE
var/list/data = get_header_data()
@@ -31,28 +31,4 @@
"charge" = round(computer.internal_cell.charge),
)
var/list/all_entries[0]
for(var/I in computer.all_components)
var/obj/item/computer_hardware/H = computer.all_components[I]
all_entries.Add(list(list(
"name" = H.name,
"desc" = H.desc,
"enabled" = H.enabled,
"critical" = H.critical,
"powerusage" = H.power_usage,
)))
data["hardware"] = all_entries
return data
/datum/computer_file/program/computerconfig/ui_act(action,params)
. = ..()
if(.)
return
switch(action)
if("PC_toggle_component")
var/obj/item/computer_hardware/H = computer.find_hardware_by_name(params["name"])
if(H && istype(H))
H.enabled = !H.enabled
. = TRUE
@@ -29,7 +29,7 @@
[GLOB.data_core ? GLOB.data_core.get_manifest_html(0) : ""]
"}
if(!computer.print_text(contents,text("crew manifest ([])", station_time_timestamp())))
to_chat(usr, span_notice("Hardware error: Printer was unable to print the file. It may be out of paper."))
to_chat(usr, span_notice("Printer is out of paper."))
return
else
computer.visible_message(span_notice("\The [computer] prints out a paper."))
@@ -71,9 +71,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
if(.)
return
var/obj/item/computer_hardware/card_slot/card_slot = computer.all_components[MC_CARD]
var/obj/item/card/id/user_id = card_slot?.stored_card
var/obj/item/card/id/user_id = computer.computer_id_slot
if(!user_id || !(ACCESS_CHANGE_IDS in user_id.access))
return
@@ -125,18 +123,19 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
var/list/data = get_header_data()
var/authed = FALSE
var/obj/item/computer_hardware/card_slot/card_slot = computer.all_components[MC_CARD]
var/obj/item/card/id/user_id = card_slot?.stored_card
var/obj/item/card/id/user_id = computer.computer_id_slot
if(user_id && (ACCESS_CHANGE_IDS in user_id.access))
authed = TRUE
data["authed"] = authed
var/list/pos = list()
for(var/j in SSjob.joinable_occupations)
var/datum/job/job = j
var/list/priority = list()
for(var/datum/job/job as anything in SSjob.joinable_occupations)
if(job.title in blacklisted)
continue
if(job in SSjob.prioritized_jobs)
priority += job.title
pos += list(list(
"title" = job.title,
@@ -146,12 +145,8 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
"status_close" = authed ? can_close_job(job) : FALSE,
))
data["slots"] = pos
data["prioritized"] = priority
var/delta = round(change_position_cooldown - ((world.time / 10) - GLOB.time_last_changed_position), 1)
data["cooldown"] = delta < 0 ? 0 : delta
var/list/priority = list()
for(var/j in SSjob.prioritized_jobs)
var/datum/job/job = j
priority += job.title
data["prioritized"] = priority
return data
@@ -33,22 +33,22 @@
return to_chat(usr, span_notice("You need to specify how much you're sending."))
if(token == current_user.pay_token)
return to_chat(usr, span_notice("You can't send credits to yourself."))
for(var/account as anything in SSeconomy.bank_accounts_by_id)
var/datum/bank_account/acc = SSeconomy.bank_accounts_by_id[account]
if(acc.pay_token == token)
recipient = acc
break
if(!recipient)
return to_chat(usr, span_notice("The app can't find who you're trying to pay. Did you enter the pay token right?"))
if(!current_user.has_money(money_to_send))
return current_user.bank_card_talk("You cannot afford it.")
recipient.bank_card_talk("You received [money_to_send] credit(s). Reason: transfer from [current_user.account_holder]")
recipient.transfer_money(current_user, money_to_send)
current_user.bank_card_talk("You send [money_to_send] credit(s) to [recipient.account_holder]. Now you have [current_user.account_balance] credit(s)")
if("GetPayToken")
wanted_token = null
for(var/account in SSeconomy.bank_accounts_by_id)
@@ -63,13 +63,8 @@
/datum/computer_file/program/nt_pay/ui_data(mob/user)
var/list/data = get_header_data()
var/obj/item/computer_hardware/card_slot/card_slot = computer.all_components[MC_CARD]
if(card_slot && card_slot.stored_card && card_slot.stored_card.registered_account)
current_user = card_slot.stored_card.registered_account
else
current_user = null
current_user = computer.computer_id_slot?.registered_account || null
if(!current_user)
data["name"] = null
else
@@ -125,12 +125,8 @@
return FALSE
/datum/computer_file/program/ntnetdownload/ui_data(mob/user)
if(!istype(computer))
return
var/obj/item/computer_hardware/card_slot/card_slot = computer.all_components[MC_CARD]
var/list/access = card_slot?.GetAccess()
var/list/data = get_header_data()
var/list/access = computer.GetAccess()
data["downloading"] = !!downloaded_file
data["error"] = downloaderror || FALSE
@@ -173,7 +169,7 @@
/datum/computer_file/program/ntnetdownload/proc/check_compatibility(datum/computer_file/program/P)
var/hardflag = computer.hardware_flag
if(P?.is_supported_by_hardware(hardflag,0))
if(P?.is_supported_by_hardware(hardware_flag = hardflag, loud = FALSE))
return TRUE
return FALSE
@@ -27,11 +27,8 @@
var/list/botlist = list()
var/list/mulelist = list()
var/obj/item/computer_hardware/card_slot/card_slot = computer ? computer.all_components[MC_CARD] : null
data["have_id_slot"] = !!card_slot
if(computer)
var/obj/item/card/id/id_card = card_slot ? card_slot.stored_card : ""
data["id_owner"] = id_card
data["id_owner"] = computer.computer_id_slot || ""
botcount = 0
@@ -91,12 +88,7 @@
if(.)
return
var/mob/current_user = ui.user
var/obj/item/computer_hardware/card_slot/card_slot
var/obj/item/card/id/id_card
if(computer)
card_slot = computer.all_components[MC_CARD]
if(card_slot)
id_card = card_slot.stored_card
var/obj/item/card/id/id_card = computer?.computer_id_slot
var/list/standard_actions = list(
"patroloff",
@@ -126,15 +118,15 @@
if("summon")
simple_bot.bot_control(action, current_user, id_card ? id_card.access : current_access)
if("ejectcard")
if(!computer || !card_slot)
if(!computer || !computer.computer_id_slot)
return
if(id_card)
GLOB.data_core.manifest_modify(id_card.registered_name, id_card.assignment, id_card.get_trim_assignment())
card_slot.try_eject(current_user)
computer.RemoveID(usr)
else
playsound(get_turf(ui_host()) , 'sound/machines/buzz-sigh.ogg', 25, FALSE)
if("changedroneaccess")
if(!computer || !card_slot || !id_card)
if(!computer || !computer.computer_id_slot || !id_card)
to_chat(current_user, span_notice("No ID found, authorization failed."))
return
if(isdrone(current_user))
@@ -92,10 +92,6 @@
. = ..()
if (.)
return
var/obj/item/computer_hardware/card_slot/card_slot
if(computer)
card_slot = computer.all_components[MC_CARD]
var/obj/item/card/id/user_id_card = card_slot?.stored_card
// Check if the console is locked to block any actions occuring
if (locked && action != "toggleLock")
@@ -107,7 +103,7 @@
if(computer.obj_flags & EMAGGED)
to_chat(usr, span_boldwarning("Security protocol error: Unable to access locking protocols."))
return TRUE
if(lock_access in user_id_card?.access)
if(lock_access in computer?.computer_id_slot?.access)
locked = !locked
else
to_chat(usr, span_boldwarning("Unauthorized Access. Please insert research ID card."))
@@ -1,127 +0,0 @@
/obj/item/computer_hardware
name = "hardware"
desc = "Unknown Hardware."
icon = 'icons/obj/module.dmi'
icon_state = "std_mod"
w_class = WEIGHT_CLASS_TINY // w_class limits which devices can contain this component.
// 1: PDAs/Tablets, 2: Laptops, 3-4: Consoles only
var/obj/item/modular_computer/holder = null
// Computer that holds this hardware, if any.
/// If the hardware uses extra power, change this.
var/power_usage = 0
/// If the hardware is turned off set this to 0.
var/enabled = TRUE
/// Prevent disabling for important component, like the CPU.
var/critical = FALSE
/// Prevents direct installation of removable media.
var/can_install = TRUE
/// Hardware that fits into expansion bays.
var/expansion_hw = FALSE
/// Whether the hardware is removable or not.
var/removable = TRUE
/// Current damage level
var/damage = 0
// Maximal damage level.
var/max_damage = 100
/// "Malfunction" threshold. When damage exceeds this value the hardware piece will semi-randomly fail and do !!FUN!! things
var/damage_malfunction = 20
/// "Failure" threshold. When damage exceeds this value the hardware piece will not work at all.
var/damage_failure = 50
/// Chance of malfunction when the component is damaged
var/malfunction_probability = 10
/// What define is used to qualify this piece of hardware? Important for upgraded versions of the same hardware.
var/device_type
/obj/item/computer_hardware/New(obj/L)
..()
pixel_x = base_pixel_x + rand(-8, 8)
pixel_y = base_pixel_y + rand(-8, 8)
/obj/item/computer_hardware/Destroy()
if(holder)
holder.forget_component(src)
return ..()
/obj/item/computer_hardware/attackby(obj/item/I, mob/living/user)
// 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(atom_integrity == max_integrity)
to_chat(user, span_warning("\The [src] doesn't seem to require repairs."))
return 1
if(S.use(1))
to_chat(user, span_notice("You patch up \the [src] with a bit of \the [I]."))
atom_integrity = min(atom_integrity + 10, max_integrity)
return 1
if(try_insert(I, user))
return TRUE
return ..()
/obj/item/computer_hardware/multitool_act(mob/living/user, obj/item/I)
..()
to_chat(user, "***** DIAGNOSTICS REPORT *****")
diagnostics(user)
to_chat(user, "******************************")
return TRUE
/// 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"]")
/// Handles damage checks
/obj/item/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/computer_hardware/examine(mob/user)
. = ..()
if(damage > damage_failure)
. += span_danger("It seems to be severely damaged!")
else if(damage > damage_malfunction)
. += span_warning("It seems to be damaged!")
else if(damage)
. += span_notice("It seems to be slightly damaged.")
/// Component-side compatibility check.
/obj/item/computer_hardware/proc/can_install(obj/item/modular_computer/install_into, mob/living/user = null)
return can_install
/// Called when component is installed into PC.
/obj/item/computer_hardware/proc/on_install(obj/item/modular_computer/install_into, mob/living/user = null)
return
/// Called when component is removed from PC.
/obj/item/computer_hardware/proc/on_remove(obj/item/modular_computer/remove_from, mob/living/user)
if(remove_from.physical && !QDELETED(remove_from) && !QDELETED(src))
try_eject(forced = TRUE)
/// Called when someone tries to insert something in it - paper in printer, card in card reader, etc.
/obj/item/computer_hardware/proc/try_insert(obj/item/I, mob/living/user = null)
return FALSE
/**
* Implement this when your hardware contains an object that the user can eject.
*
* Examples include ejecting cells from battery modules, ejecting an ID card from a card reader
* or ejecting an Intellicard from an AI card slot.
* Arguments:
* * user - The mob requesting the eject.
* * forced - Whether this action should be forced in some way.
*/
/obj/item/computer_hardware/proc/try_eject(mob/living/user = null, forced = FALSE)
return FALSE
@@ -1,146 +0,0 @@
/obj/item/computer_hardware/card_slot
name = "primary RFID card module" // \improper breaks the find_hardware_by_name proc
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
icon_state = "card_mini"
w_class = WEIGHT_CLASS_TINY
device_type = MC_CARD
var/obj/item/card/id/stored_card
var/current_identification = null
var/current_job = null
///What happens when the ID card is removed (or deleted) from the module, through try_eject() or not.
/obj/item/computer_hardware/card_slot/Exited(atom/movable/gone, direction)
if(stored_card == gone)
stored_card = null
if(holder)
if(holder.active_program)
holder.active_program.event_idremoved(0)
for(var/datum/computer_file/program/computer_program as anything in holder.idle_threads)
computer_program.event_idremoved(1)
holder.update_slot_icon()
if(ishuman(holder.loc))
var/mob/living/carbon/human/human_wearer = holder.loc
if(human_wearer.wear_id == holder)
human_wearer.sec_hud_set_ID()
return ..()
/obj/item/computer_hardware/card_slot/Destroy()
if(stored_card) //If you didn't expect this behavior for some dumb reason, do something different instead of directly destroying the slot
QDEL_NULL(stored_card)
return ..()
/obj/item/computer_hardware/card_slot/GetAccess()
var/list/total_access
if(stored_card)
total_access = stored_card.GetAccess()
var/obj/item/computer_hardware/card_slot/card_slot2 = holder?.all_components[MC_CARD2] //Best of both worlds
if(card_slot2?.stored_card)
total_access |= card_slot2.stored_card.GetAccess()
return total_access
/obj/item/computer_hardware/card_slot/GetID()
if(stored_card)
return stored_card
return ..()
/obj/item/computer_hardware/card_slot/RemoveID()
if(stored_card)
. = stored_card
if(!try_eject())
return null
return
/obj/item/computer_hardware/card_slot/try_insert(obj/item/I, mob/living/user = null)
if(!holder)
return FALSE
if(!isidcard(I))
return FALSE
if(stored_card)
return FALSE
// item instead of player is checked so telekinesis will still work if the item itself is close
if(!in_range(src, I))
return FALSE
if(user)
if(!user.transferItemToLoc(I, src))
return FALSE
else
I.forceMove(src)
stored_card = I
to_chat(user, span_notice("You insert \the [I] into \the [expansion_hw ? "secondary":"primary"] [src]."))
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE)
holder.update_appearance()
current_identification = stored_card.registered_name
current_job = stored_card.assignment
var/holder_loc = holder.loc
if(ishuman(holder_loc))
var/mob/living/carbon/human/human_wearer = holder_loc
if(human_wearer.wear_id == holder)
human_wearer.sec_hud_set_ID()
holder.update_slot_icon()
return TRUE
/obj/item/computer_hardware/card_slot/try_eject(mob/living/user = null, forced = FALSE)
if(!stored_card)
to_chat(user, span_warning("There are no cards in \the [src]."))
return FALSE
if(user && !issilicon(user) && in_range(src, user))
user.put_in_hands(stored_card)
else
stored_card.forceMove(drop_location())
balloon_alert(user, "removed ID")
to_chat(user, span_notice("You remove the card from \the [src]."))
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE)
holder?.update_appearance()
stored_card = null
current_identification = null
current_job = null
return TRUE
/obj/item/computer_hardware/card_slot/screwdriver_act(mob/living/user, obj/item/tool)
if(stored_card)
to_chat(user, span_notice("You press down on the manual eject button with [tool]."))
try_eject(user)
return TOOL_ACT_TOOLTYPE_SUCCESS
swap_slot()
to_chat(user, span_notice("You adjust the connecter to fit into [expansion_hw ? "an expansion bay" : "the primary ID bay"]."))
return TOOL_ACT_TOOLTYPE_SUCCESS
/**
*Swaps the card_slot hardware between using the dedicated card slot bay on a computer, and using an expansion bay.
*/
/obj/item/computer_hardware/card_slot/proc/swap_slot()
expansion_hw = !expansion_hw
if(expansion_hw)
device_type = MC_CARD2
name = "secondary RFID card module"
else
device_type = MC_CARD
name = "primary RFID card module"
/obj/item/computer_hardware/card_slot/examine(mob/user)
. = ..()
. += "The connector is set to fit into [expansion_hw ? "an expansion bay" : "a computer's primary ID bay"], but can be adjusted with a screwdriver."
if(stored_card)
. += "There appears to be something loaded in the card slots."
/obj/item/computer_hardware/card_slot/secondary
name = "secondary RFID card module"
device_type = MC_CARD2
expansion_hw = TRUE
@@ -18,9 +18,6 @@
var/total_price = 0 // Price of currently vended device.
var/credits = 0
// Device loadout
var/dev_card = 0 // 0: None, 1: Standard
// Removes all traces of old order and allows you to begin configuration from scratch.
/obj/machinery/lapvend/proc/reset_order()
state = 0
@@ -31,7 +28,6 @@
if(fabricated_tablet)
qdel(fabricated_tablet)
fabricated_tablet = null
dev_card = 0
// Recalculates the price and optionally even fabricates the device.
/obj/machinery/lapvend/proc/fabricate_and_recalc_price(fabricate = FALSE)
@@ -39,24 +35,13 @@
if(devtype == 1) // Laptop, generally cheaper to make it accessible for most station roles
if(fabricate)
fabricated_laptop = new /obj/item/modular_computer/laptop/buildable(src)
fabricated_laptop.install_component(new /obj/item/computer_hardware/card_slot)
total_price = 99
if(dev_card)
total_price += 199
if(fabricate)
fabricated_laptop.install_component(new /obj/item/computer_hardware/card_slot/secondary)
return total_price
else if(devtype == 2) // Tablet, more expensive, not everyone could probably afford this.
if(fabricate)
fabricated_tablet = new(src)
fabricated_tablet.install_component(new/obj/item/computer_hardware/card_slot)
total_price = 199
if(dev_card)
total_price += 199
if(fabricate)
fabricated_tablet.install_component(new/obj/item/computer_hardware/card_slot/secondary)
return total_price
return FALSE
/obj/machinery/lapvend/ui_act(action, params)
@@ -85,10 +70,6 @@
state = 2 // Wait for ID swipe for payment processing
fabricate_and_recalc_price(FALSE)
return TRUE
if("hw_card")
dev_card = text2num(params["card"])
fabricate_and_recalc_price(FALSE)
return TRUE
return FALSE
/obj/machinery/lapvend/ui_interact(mob/user, datum/tgui/ui)
@@ -145,7 +126,6 @@
data["state"] = state
if(state == 1)
data["devtype"] = devtype
data["hw_card"] = dev_card
if(state == 1 || state == 2)
data["totalprice"] = total_price
data["credits"] = credits