Modular Tablets: Converting PDAs to the NtOS System (#65755)

Converts PDA functions and applications over to modular tablets and devices, namely the messaging function. HREF data code is quite honestly clunky and difficult to work with, as I've definitely experienced whilst working on this. By moving from this system over the easier to read (and frankly, easier to add to) TGUI system, you get cleaner looking and more user friendly UIs and a greater degree of standardization amongst other UIs.

Co-authored-by: Seth Scherer <supernovaa41@gmx.com>
Co-authored-by: GoldenAlpharex <58045821+GoldenAlpharex@users.noreply.github.com>
Co-authored-by: Aleksej Komarov <stylemistake@gmail.com>
This commit is contained in:
magatsuchi
2022-04-19 19:08:41 -05:00
committed by GitHub
parent ee7f0d0a60
commit cd1b891d79
146 changed files with 2733 additions and 3321 deletions
@@ -1,3 +1,5 @@
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.
// Other types expand it - tablets use a direct subtypes, and
// consoles and laptops use "procssor" item that is held inside machinery piece
@@ -11,7 +13,11 @@
max_integrity = 100
armor = list(MELEE = 0, BULLET = 20, LASER = 20, ENERGY = 100, BOMB = 0, BIO = 100, FIRE = 0, ACID = 0)
var/bypass_state = FALSE // bypassing the set icon state
var/enabled = 0 // Whether the computer is turned on.
var/upgradable = TRUE // whether or not the computer can be upgraded
var/deconstructable = TRUE // whether or not the computer can be deconstructed
var/screen_on = 1 // Whether the computer is active/opened/it's screen is on.
var/device_theme = "ntos" // Sets the theme for the main menu, hardware config, and file browser apps. Overridden by certain non-NT devices.
var/datum/computer_file/program/active_program = null // A currently active program running on the computer.
@@ -46,14 +52,26 @@
/// Number of total expansion bays this computer has available.
var/max_bays = 0
var/saved_identification = null // next two values are the currently imprinted id and job values
var/saved_job = null
var/honkamnt = 0 /// honk honk honk honk honk honkh onk honkhnoohnk
var/list/idle_threads // Idle programs on background. They still receive process calls but can't be interacted with.
var/obj/physical = null // Object that represents our computer. It's used for Adjacent() and UI visibility checks.
var/has_light = FALSE //If the computer has a flashlight/LED light/what-have-you installed
var/comp_light_luminosity = 3 //The brightness of that light
var/comp_light_color //The color of that light
var/invisible = FALSE // whether or not the tablet is invisible in messenger and other apps
var/datum/picture/saved_image // the saved image used for messaging purpose like come on dude
var/obj/item/paicard/pai = null
/obj/item/modular_computer/Initialize(mapload)
. = ..()
var/obj/item/computer_hardware/identifier/id = all_components[MC_IDENTIFY]
START_PROCESSING(SSobj, src)
if(!physical)
physical = src
@@ -61,20 +79,28 @@
idle_threads = list()
if(looping_sound)
soundloop = new(src, enabled)
if(id)
id.UpdateDisplay()
update_appearance()
Add_Messenger()
/obj/item/modular_computer/Destroy()
wipe_program(forced = TRUE)
for(var/datum/computer_file/program/idle as anything in idle_threads)
idle.kill_program(TRUE)
idle_threads.Cut()
idle_threads?.Cut()
STOP_PROCESSING(SSobj, src)
for(var/port in all_components)
var/obj/item/computer_hardware/component = all_components[port]
qdel(component)
all_components.Cut() //Die demon die
all_components?.Cut()
//Some components will actually try and interact with this, so let's do it later
QDEL_NULL(soundloop)
Remove_Messenger()
if(istype(pai))
QDEL_NULL(pai)
physical = null
return ..()
@@ -86,6 +112,16 @@
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
return ..()
// shameless copy of newscaster photo saving
/obj/item/modular_computer/proc/save_photo(icon/photo)
var/photo_file = copytext_char(md5("\icon[photo]"), 1, 6)
if(!fexists("[GLOB.log_directory]/photos/[photo_file].png"))
//Clean up repeated frames
var/icon/clean = new /icon()
clean.Insert(photo, "", SOUTH, 1, 0)
fcopy(clean, "[GLOB.log_directory]/photos/[photo_file].png")
return photo_file
/**
* Plays a ping sound.
@@ -103,7 +139,10 @@
if(user.canUseTopic(src, BE_CLOSE))
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]
return (card_slot2?.try_eject(user) || card_slot?.try_eject(user)) //Try the secondary one first.
if(card_slot2?.try_eject(user) || card_slot?.try_eject(user))
return TRUE
if(!istype(src, /obj/item/modular_computer/tablet))
return FALSE
// Gets IDs/access levels from card slot. Would be useful when/if PDAs would become modular PCs.
/obj/item/modular_computer/GetAccess()
@@ -169,6 +208,8 @@
if(human_wearer.wear_id == src)
human_wearer.sec_hud_set_ID()
update_slot_icon()
update_appearance()
return removed_id
return ..()
@@ -176,10 +217,11 @@
/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))
return FALSE
var/obj/item/card/inserting_id = inserting_item.RemoveID()
var/obj/item/card/inserting_id = inserting_item.GetID()
if(!inserting_id)
return FALSE
@@ -188,8 +230,8 @@
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
return FALSE
@@ -241,19 +283,24 @@
. += get_modular_computer_parts_examine(user)
/obj/item/modular_computer/update_icon_state()
icon_state = enabled ? icon_state_powered : icon_state_unpowered
if(!bypass_state)
icon_state = enabled ? icon_state_powered : icon_state_unpowered
return ..()
/obj/item/modular_computer/update_overlays()
. = ..()
var/init_icon = initial(icon)
if(!init_icon)
return
if(!display_overlays)
return
if(enabled)
. += active_program?.program_icon_state || icon_state_menu
. += active_program ? mutable_appearance(init_icon, active_program.program_icon_state) : mutable_appearance(init_icon, icon_state_menu)
if(atom_integrity <= integrity_failure * max_integrity)
. += "bsod"
. += "broken"
. += mutable_appearance(init_icon, "bsod")
. += mutable_appearance(init_icon, "broken")
// On-click handling. Turns on the computer if it's off and opens the GUI.
@@ -353,6 +400,16 @@
if(istype(holder))
to_chat(holder, "[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))
playsound(src, pick('sound/machines/twobeep_voice1.ogg', 'sound/machines/twobeep_voice2.ogg'), 50, TRUE)
else
playsound(src, 'sound/machines/twobeep_high.ogg', 50, TRUE)
visible_message("*[ringtone]*")
/obj/item/modular_computer/proc/send_sound()
playsound(src, 'sound/machines/terminal_success.ogg', 15, TRUE)
// Function used by NanoUI's to obtain data for header. All relevant entries begin with "PC_"
/obj/item/modular_computer/proc/get_header_data()
var/list/data = list()
@@ -489,6 +546,8 @@
return TRUE
/obj/item/modular_computer/screwdriver_act(mob/user, obj/item/tool)
if(!deconstructable)
return
if(!length(all_components))
balloon_alert(user, "no components installed!")
return
@@ -520,6 +579,25 @@
if(istype(W, /obj/item/card/id) && InsertID(W))
return
// Insert a PAI.
if(istype(W, /obj/item/paicard) && !pai)
if(!user.transferItemToLoc(W, src))
return
pai = W
pai.slotted = TRUE
to_chat(user, span_notice("You slot \the [W] into [src]."))
return
// Scan a photo.
if(istype(W, /obj/item/photo))
var/obj/item/computer_hardware/hard_drive/hdd = all_components[MC_HDD]
var/obj/item/photo/pic = W
if(hdd)
for(var/datum/computer_file/program/messenger/messenger in hdd.stored_files)
saved_image = pic.picture
messenger.ProcessPhoto()
return
// Insert items into the components
for(var/h in all_components)
var/obj/item/computer_hardware/H = all_components[h]
@@ -527,7 +605,7 @@
return
// Insert new hardware
if(istype(W, /obj/item/computer_hardware))
if(istype(W, /obj/item/computer_hardware) && upgradable)
if(install_component(W, user))
return
@@ -574,3 +652,9 @@
if(physical && physical != src)
return physical.Adjacent(neighbor)
return ..()
/obj/item/modular_computer/proc/Add_Messenger()
GLOB.TabletMessengers += src
/obj/item/modular_computer/proc/Remove_Messenger()
GLOB.TabletMessengers -= src
@@ -4,6 +4,8 @@
// Operates TGUI
/obj/item/modular_computer/ui_interact(mob/user, datum/tgui/ui)
if(issilicon(user)) // silicons have some issues regarding real_name
saved_identification = user.real_name
if(!enabled)
if(ui)
ui.close()
@@ -37,6 +39,10 @@
to_chat(user, span_danger("\The [src] beeps three times, it's screen displaying a \"DISK ERROR\" warning."))
return // No HDD, No HDD files list or no stored files. Something is very broken.
if(honkamnt > 0) // EXTRA annoying, huh!
honkamnt--
playsound(src, 'sound/items/bikehorn.ogg', 30, TRUE)
ui = SStgui.try_update_ui(user, src, ui)
if (!ui)
ui = new(user, src, "NtosMain")
@@ -44,28 +50,55 @@
if(ui.open())
ui.send_asset(get_asset_datum(/datum/asset/simple/headers))
/obj/item/modular_computer/ui_static_data(mob/user)
. = ..()
var/list/data = list()
data["show_imprint"] = istype(src, /obj/item/modular_computer/tablet/)
return data
/obj/item/modular_computer/ui_data(mob/user)
var/list/data = get_header_data()
data["device_theme"] = device_theme
data["login"] = list()
data["disk"] = null
var/obj/item/computer_hardware/card_slot/cardholder = all_components[MC_CARD]
var/obj/item/computer_hardware/hard_drive/role/ssd = all_components[MC_HDD_JOB]
data["cardholder"] = FALSE
if(cardholder)
data["cardholder"] = TRUE
var/obj/item/card/id/stored_card = cardholder.GetID()
if(stored_card)
var/stored_name = stored_card.registered_name
var/stored_title = stored_card.assignment
if(!stored_name)
stored_name = "Unknown"
if(!stored_title)
stored_title = "Unknown"
data["login"] = list(
IDName = stored_name,
IDJob = stored_title,
)
var/stored_name = saved_identification
var/stored_title = saved_job
if(!stored_name)
stored_name = "Unknown"
if(!stored_title)
stored_title = "Unknown"
data["login"] = list(
IDName = saved_identification,
IDJob = saved_job,
)
data["proposed_login"] = list(
IDName = cardholder.current_identification,
IDJob = cardholder.current_job,
)
if(ssd)
data["disk"] = ssd
data["disk_name"] = ssd.name
for(var/datum/computer_file/program/prog in ssd.stored_files)
var/running = FALSE
if(prog in idle_threads)
running = TRUE
data["disk_programs"] += list(list("name" = prog.filename, "desc" = prog.filedesc, "running" = running, "icon" = prog.program_icon, "alert" = prog.alert_pending))
data["removable_media"] = list()
if(all_components[MC_SDD])
@@ -89,6 +122,7 @@
data["has_light"] = has_light
data["light_on"] = light_on
data["comp_light_color"] = comp_light_color
data["pai"] = pai
return data
@@ -134,10 +168,15 @@
if("PC_runprogram")
var/prog = params["name"]
var/is_disk = params["is_disk"]
var/datum/computer_file/program/P = null
var/obj/item/computer_hardware/hard_drive/role/ssd = all_components[MC_HDD_JOB]
var/mob/user = usr
if(hard_drive)
if(hard_drive && !is_disk)
P = hard_drive.find_file_by_name(prog)
if(ssd && is_disk)
P = ssd.find_file_by_name(prog)
if(!P || !istype(P)) // Program not found or it's not executable program.
to_chat(user, span_danger("\The [src]'s screen shows \"I/O ERROR - Unable to run program\" warning."))
@@ -198,6 +237,13 @@
if(uninstall_component(portable_drive, usr))
user.put_in_hands(portable_drive)
playsound(src, 'sound/machines/card_slide.ogg', 50)
if("job disk")
var/obj/item/computer_hardware/hard_drive/role/ssd = all_components[MC_HDD_JOB]
if(!ssd)
return
if(uninstall_component(ssd, usr))
user.put_in_hands(ssd)
playsound(src, 'sound/machines/card_slide.ogg', 50)
if("intelliCard")
var/obj/item/computer_hardware/ai_slot/intelliholder = all_components[MC_AI]
if(!intelliholder)
@@ -208,14 +254,37 @@
var/obj/item/computer_hardware/card_slot/cardholder = all_components[MC_CARD]
if(!cardholder)
return
cardholder.try_eject(user)
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
cardholder.try_eject(user)
if(cardholder.try_eject(user))
playsound(src, 'sound/machines/card_slide.ogg', 50)
if("PC_Imprint_ID")
var/obj/item/computer_hardware/card_slot/cardholder = all_components[MC_CARD]
var/obj/item/computer_hardware/identifier/id_hardware = all_components[MC_IDENTIFY]
if(!cardholder)
return
saved_identification = cardholder.current_identification
saved_job = cardholder.current_job
if(id_hardware)
id_hardware.UpdateDisplay()
playsound(src, 'sound/machines/terminal_processing.ogg', 15, TRUE)
if("PC_Pai_Interact")
switch(params["option"])
if("eject")
usr.put_in_hands(pai)
pai.slotted = FALSE
pai = null
to_chat(usr, span_notice("You remove the pAI from the [name]."))
if("interact")
pai.attack_self(usr)
return UI_UPDATE
else
return
@@ -0,0 +1,227 @@
/obj/item/modular_computer/tablet/pda/medical
name = "medical PDA"
default_disk = /obj/item/computer_hardware/hard_drive/role/medical
greyscale_config = /datum/greyscale_config/tablet/stripe_thick
greyscale_colors = "#e2e2e2#000099#5d99be"
/obj/item/modular_computer/tablet/pda/viro
name = "virology PDA"
default_disk = /obj/item/computer_hardware/hard_drive/role/medical
greyscale_config = /datum/greyscale_config/tablet/stripe_split
greyscale_colors = "#e2e2e2#355FAC#789876"
/obj/item/modular_computer/tablet/pda/engineering
name = "engineering PDA"
default_disk = /obj/item/computer_hardware/hard_drive/role/engineering
greyscale_config = /datum/greyscale_config/tablet/stripe_thick
greyscale_colors = "#C5994C#69DBF3#D9D65B"
/obj/item/modular_computer/tablet/pda/security
name = "security PDA"
default_disk = /obj/item/computer_hardware/hard_drive/role/security
greyscale_colors = "#cc4242#0000cc"
/obj/item/modular_computer/tablet/pda/detective
name = "detective PDA"
default_disk = /obj/item/computer_hardware/hard_drive/role/detective
greyscale_colors = "#90714F#990202"
/obj/item/modular_computer/tablet/pda/warden
name = "warden PDA"
default_disk = /obj/item/computer_hardware/hard_drive/role/security
greyscale_config = /datum/greyscale_config/tablet/stripe_split
greyscale_colors = "#cc4242#0000cc#666666"
/obj/item/modular_computer/tablet/pda/janitor
name = "janitor PDA"
default_disk = /obj/item/computer_hardware/hard_drive/role/janitor
greyscale_colors = "#933ea8#235AB2"
/obj/item/modular_computer/tablet/pda/science
name = "scientist PDA"
default_disk = /obj/item/computer_hardware/hard_drive/role/signal/ordnance
greyscale_config = /datum/greyscale_config/tablet/stripe_thick
greyscale_colors = "#e2e2e2#000099#9F5CA5"
/obj/item/modular_computer/tablet/pda/heads
default_disk = /obj/item/computer_hardware/hard_drive/role/head
greyscale_config = /datum/greyscale_config/tablet/head
greyscale_colors = "#789876#a92323"
/obj/item/modular_computer/tablet/pda/heads/hop
name = "head of personnel PDA"
default_disk = /obj/item/computer_hardware/hard_drive/role/hop
/obj/item/modular_computer/tablet/pda/heads/hos
name = "head of security PDA"
default_disk = /obj/item/computer_hardware/hard_drive/role/hos
greyscale_config = /datum/greyscale_config/tablet/head
greyscale_colors = "#cc4242#0000cc"
/obj/item/modular_computer/tablet/pda/heads/ce
name = "chief engineer PDA"
default_disk = /obj/item/computer_hardware/hard_drive/role/ce
greyscale_config = /datum/greyscale_config/tablet/stripe_thick/head
greyscale_colors = "#C4A56D#69DBF3#e2e2e2"
/obj/item/modular_computer/tablet/pda/heads/cmo
name = "chief medical officer PDA"
default_disk = /obj/item/computer_hardware/hard_drive/role/cmo
greyscale_config = /datum/greyscale_config/tablet/stripe_thick/head
greyscale_colors = "#e2e2e2#000099#5d99be"
/obj/item/modular_computer/tablet/pda/heads/rd
name = "research director PDA"
default_disk = /obj/item/computer_hardware/hard_drive/role/rd
greyscale_config = /datum/greyscale_config/tablet/stripe_thick/head
greyscale_colors = "#e2e2e2#000099#9F5CA5"
insert_type = /obj/item/pen/fountain
/obj/item/modular_computer/tablet/pda/captain
name = "captain PDA"
default_disk = /obj/item/computer_hardware/hard_drive/role/captain
greyscale_config = /datum/greyscale_config/tablet/captain
greyscale_colors = "#2C7CB2#FF0000#FFFFFF#F5D67B"
insert_type = /obj/item/pen/fountain
/obj/item/modular_computer/tablet/pda/captain/Initialize(mapload)
. = ..()
RegisterSignal(src, COMSIG_TABLET_CHECK_DETONATE, .proc/tab_no_detonate)
/obj/item/modular_computer/tablet/pda/cargo
name = "cargo technician PDA"
default_disk = /obj/item/computer_hardware/hard_drive/role/quartermaster
greyscale_colors = "#D6B328#6506ca"
/obj/item/modular_computer/tablet/pda/quartermaster/Initialize(mapload)
. = ..()
install_component(new /obj/item/computer_hardware/printer/mini)
/obj/item/modular_computer/tablet/pda/quartermaster
name = "quartermaster PDA"
default_disk = /obj/item/computer_hardware/hard_drive/role/quartermaster
greyscale_config = /datum/greyscale_config/tablet/stripe_thick
greyscale_colors = "#D6B328#6506ca#927444"
/obj/item/modular_computer/tablet/pda/quartermaster/Initialize(mapload)
. = ..()
install_component(new /obj/item/computer_hardware/printer/mini)
/obj/item/modular_computer/tablet/pda/shaftminer
name = "shaft miner PDA"
greyscale_config = /datum/greyscale_config/tablet/stripe_thick
greyscale_colors = "#927444#D6B328#6C3BA1"
/obj/item/modular_computer/tablet/pda/chaplain
name = "chaplain PDA"
greyscale_config = /datum/greyscale_config/tablet/chaplain
greyscale_colors = "#333333#d11818"
/obj/item/modular_computer/tablet/pda/lawyer
name = "lawyer PDA"
default_disk = /obj/item/computer_hardware/hard_drive/role/lawyer
greyscale_colors = "#5B74A5#f7e062"
insert_type = /obj/item/pen/fountain
/obj/item/modular_computer/tablet/pda/botanist
name = "botanist PDA"
greyscale_config = /datum/greyscale_config/tablet/stripe_thick
greyscale_colors = "#50E193#E26F41#71A7CA"
/obj/item/modular_computer/tablet/pda/roboticist
name = "roboticist PDA"
greyscale_config = /datum/greyscale_config/tablet/stripe_split
greyscale_colors = "#484848#0099cc#d33725"
default_disk = /obj/item/computer_hardware/hard_drive/role/roboticist
/obj/item/modular_computer/tablet/pda/cook
name = "cook PDA"
greyscale_colors = "#e2e2e2#a92323"
/obj/item/modular_computer/tablet/pda/bar
name = "bartender PDA"
greyscale_colors = "#333333#c7c7c7"
/obj/item/modular_computer/tablet/pda/atmos
name = "atmospherics PDA"
default_disk = /obj/item/computer_hardware/hard_drive/role/atmos
greyscale_config = /datum/greyscale_config/tablet/stripe_thick
greyscale_colors = "#ceca2b#00E5DA#727272"
/obj/item/modular_computer/tablet/pda/chemist
name = "chemist PDA"
default_disk = /obj/item/computer_hardware/hard_drive/role/chemistry
greyscale_config = /datum/greyscale_config/tablet/stripe_thick
greyscale_colors = "#e2e2e2#355FAC#ea6400"
/obj/item/modular_computer/tablet/pda/geneticist
name = "geneticist PDA"
default_disk = /obj/item/computer_hardware/hard_drive/role/medical
greyscale_config = /datum/greyscale_config/tablet/stripe_split
greyscale_colors = "#e2e2e2#000099#0097ca"
/obj/item/modular_computer/tablet/pda/clown
name = "clown PDA"
default_disk = /obj/item/computer_hardware/hard_drive/role/virus/clown
icon_state = "pda-clown"
greyscale_config = null
greyscale_colors = null
insert_type = /obj/item/toy/crayon/rainbow
/obj/item/modular_computer/tablet/pda/clown/ComponentInitialize()
. = ..()
AddComponent(/datum/component/slippery/clowning, 120, NO_SLIP_WHEN_WALKING, CALLBACK(src, .proc/AfterSlip), slot_whitelist = list(ITEM_SLOT_ID, ITEM_SLOT_BELT))
AddComponent(/datum/component/wearertargeting/sitcomlaughter, CALLBACK(src, .proc/after_sitcom_laugh))
/obj/item/modular_computer/tablet/pda/clown/update_overlays()
. = ..()
. += mutable_appearance(icon, "pda_stripe_clown") // clowns have eyes that go over their screen, so it needs to be compiled last
/obj/item/modular_computer/tablet/pda/clown/proc/AfterSlip(mob/living/carbon/human/M)
if (istype(M) && (M.real_name != saved_identification))
var/obj/item/computer_hardware/hard_drive/role/virus/clown/cart = all_components[MC_HDD_JOB]
if(istype(cart) && cart.charges < 5)
cart.charges++
playsound(src,'sound/machines/ping.ogg',30,TRUE)
/obj/item/modular_computer/tablet/pda/clown/proc/after_sitcom_laugh(mob/victim)
victim.visible_message("[src] lets out a burst of laughter!")
/obj/item/modular_computer/tablet/pda/mime
name = "mime PDA"
default_disk = /obj/item/computer_hardware/hard_drive/role/virus/mime
greyscale_config = /datum/greyscale_config/tablet/mime
greyscale_colors = "#e2e2e2#cc4242"
insert_type = /obj/item/toy/crayon/mime
/obj/item/modular_computer/tablet/pda/mime/Initialize(mapload)
. = ..()
var/obj/item/computer_hardware/hard_drive/hdd = all_components[MC_HDD]
if(hdd)
for(var/datum/computer_file/program/messenger/msg in hdd.stored_files)
msg.mime_mode = TRUE
msg.allow_emojis = TRUE
/obj/item/modular_computer/tablet/pda/curator
name = "curator PDA"
default_disk = /obj/item/computer_hardware/hard_drive/role/curator
greyscale_config = null
greyscale_colors = null
icon_state = "pda-library"
insert_type = /obj/item/pen/fountain
display_overlays = FALSE
/obj/item/modular_computer/tablet/pda/syndicate
name = "military PDA"
greyscale_colors = "#891417#80FF80"
saved_identification = "John Doe"
saved_job = "Citizen"
invisible = TRUE
/obj/item/modular_computer/tablet/pda/clear
name = "clear PDA"
icon_state = "pda-clear"
greyscale_config = null
greyscale_colors = null
@@ -16,16 +16,95 @@
has_light = TRUE //LED flashlight!
comp_light_luminosity = 2.3 //Same as the PDA
looping_sound = FALSE
var/has_variants = TRUE
var/finish_color = null
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
/obj/item/modular_computer/tablet/update_icon_state()
if(has_variants)
if(has_variants && !bypass_state)
if(!finish_color)
finish_color = pick("red", "blue", "brown", "green", "black")
icon_state = icon_state_powered = icon_state_unpowered = "[base_icon_state]-[finish_color]"
return ..()
/obj/item/modular_computer/tablet/interact(mob/user)
. = ..()
if(HAS_TRAIT(src, TRAIT_PDA_MESSAGE_MENU_RIGGED))
explode(usr, from_message_menu = TRUE)
return
/obj/item/modular_computer/tablet/attackby(obj/item/W, mob/user)
. = ..()
if(is_type_in_list(W, contained_item))
if(inserted_item)
to_chat(user, span_warning("There is already \a [inserted_item] in \the [src]!"))
else
if(!user.transferItemToLoc(W, src))
return
to_chat(user, span_notice("You insert \the [W] into \the [src]."))
inserted_item = W
playsound(src, 'sound/machines/pda_button1.ogg', 50, TRUE)
/obj/item/modular_computer/tablet/AltClick(mob/user)
. = ..()
if(.)
return
remove_pen(user)
/obj/item/modular_computer/tablet/proc/tab_no_detonate()
SIGNAL_HANDLER
return COMPONENT_TABLET_NO_DETONATE
/obj/item/modular_computer/tablet/proc/remove_pen(mob/user)
if(issilicon(user) || !user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK)) //TK doesn't work even with this removed but here for readability
return
if(inserted_item)
to_chat(user, span_notice("You remove [inserted_item] from [src]."))
user.put_in_hands(inserted_item)
inserted_item = null
update_appearance()
playsound(src, 'sound/machines/pda_button2.ogg', 50, TRUE)
else
to_chat(user, span_warning("This tablet does not have a pen in it!"))
// Tablet 'splosion..
/obj/item/modular_computer/tablet/proc/explode(mob/target, mob/bomber, from_message_menu = FALSE)
var/turf/T = get_turf(src)
if(from_message_menu)
log_bomber(null, null, target, "'s tablet exploded as [target.p_they()] tried to open their tablet message menu because of a recent tablet bomb.")
else
log_bomber(bomber, "successfully tablet-bombed", target, "as [target.p_they()] tried to reply to a rigged tablet message [bomber && !is_special_character(bomber) ? "(SENT BY NON-ANTAG)" : ""]")
if (ismob(loc))
var/mob/M = loc
M.show_message(span_userdanger("Your [src] explodes!"), MSG_VISUAL, span_warning("You hear a loud *pop*!"), MSG_AUDIBLE)
else
visible_message(span_danger("[src] explodes!"), span_warning("You hear a loud *pop*!"))
target.client?.give_award(/datum/award/achievement/misc/clickbait, target)
if(T)
T.hotspot_expose(700,125)
if(istype(all_components[MC_HDD_JOB], /obj/item/computer_hardware/hard_drive/role/virus/deto))
explosion(src, devastation_range = -1, heavy_impact_range = 1, light_impact_range = 3, flash_range = 4)
else
explosion(src, devastation_range = -1, heavy_impact_range = -1, light_impact_range = 2, flash_range = 3)
qdel(src)
// SUBTYPES
/obj/item/modular_computer/tablet/syndicate_contract_uplink
name = "contractor tablet"
icon = 'icons/obj/contractor_tablet.dmi'
@@ -65,8 +144,8 @@
has_light = FALSE //tablet light button actually enables/disables the borg lamp
comp_light_luminosity = 0
has_variants = FALSE
///Ref to the borg we're installed in. Set by the borg during our creation.
var/mob/living/silicon/robot/borgo
///Ref to the silicon we're installed in. Set by the borg during our creation.
var/mob/living/silicon/borgo
///Ref to the RoboTact app. Important enough to borgs to deserve a ref.
var/datum/computer_file/program/robotact/robotact
///IC log that borgs can view in their personal management app
@@ -119,22 +198,28 @@
/obj/item/modular_computer/tablet/integrated/ui_data(mob/user)
. = ..()
.["has_light"] = TRUE
.["light_on"] = borgo?.lamp_enabled
.["comp_light_color"] = borgo?.lamp_color
if(istype(borgo, /mob/living/silicon/robot))
var/mob/living/silicon/robot/robo = borgo
.["light_on"] = robo.lamp_enabled
.["comp_light_color"] = robo.lamp_color
//Makes the flashlight button affect the borg rather than the tablet
/obj/item/modular_computer/tablet/integrated/toggle_flashlight()
if(!borgo || QDELETED(borgo))
return FALSE
borgo.toggle_headlamp()
if(istype(borgo, /mob/living/silicon/robot))
var/mob/living/silicon/robot/robo = borgo
robo.toggle_headlamp()
return TRUE
//Makes the flashlight color setting affect the borg rather than the tablet
/obj/item/modular_computer/tablet/integrated/set_flashlight_color(color)
if(!borgo || QDELETED(borgo) || !color)
return FALSE
borgo.lamp_color = color
borgo.toggle_headlamp(FALSE, TRUE)
if(istype(borgo, /mob/living/silicon/robot))
var/mob/living/silicon/robot/robo = borgo
robo.lamp_color = color
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')
@@ -143,6 +228,8 @@
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
/obj/item/modular_computer/tablet/integrated/syndicate
icon_state = "tablet-silicon-syndicate"
@@ -153,4 +240,51 @@
/obj/item/modular_computer/tablet/integrated/syndicate/Initialize(mapload)
. = ..()
borgo.lamp_color = COLOR_RED //Syndicate likes it red
if(istype(borgo, /mob/living/silicon/robot))
var/mob/living/silicon/robot/robo = borgo
robo.lamp_color = COLOR_RED //Syndicate likes it red
// Round start tablets
/obj/item/modular_computer/tablet/pda
icon_state = "pda"
greyscale_config = /datum/greyscale_config/tablet
greyscale_colors = "#999875#a92323"
bypass_state = TRUE
var/default_disk = 0
/obj/item/modular_computer/tablet/pda/update_overlays()
. = ..()
var/init_icon = initial(icon)
var/obj/item/computer_hardware/card_slot/card = all_components[MC_CARD]
if(!init_icon)
return
if(card)
if(card.stored_card)
. += mutable_appearance(init_icon, "id_overlay")
if(light_on)
. += mutable_appearance(init_icon, "light_overlay")
/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/hard_drive/small)
install_component(new /obj/item/computer_hardware/processor_unit/small)
install_component(new /obj/item/computer_hardware/battery(src, /obj/item/stock_parts/cell/computer))
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/identifier)
install_component(new /obj/item/computer_hardware/sensorpackage)
if(default_disk)
var/obj/item/computer_hardware/hard_drive/portable/disk = new default_disk(src)
install_component(disk)
if(insert_type)
inserted_item = new insert_type(src)
@@ -107,6 +107,5 @@
/obj/item/modular_computer/tablet/integrated/Initialize(mapload)
. = ..()
install_component(new /obj/item/computer_hardware/processor_unit/small)
install_component(new /obj/item/computer_hardware/hard_drive/small/integrated)
install_component(new /obj/item/computer_hardware/recharger/cyborg)
install_component(new /obj/item/computer_hardware/network_card/integrated)