mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-22 04:30:44 +01:00
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:
co-authored by
Seth Scherer
GoldenAlpharex
Aleksej Komarov
parent
ee7f0d0a60
commit
cd1b891d79
@@ -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)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
filedesc = "Newscaster"
|
||||
required_access = list(ACCESS_LIBRARY)
|
||||
category = PROGRAM_CATEGORY_CREW
|
||||
program_icon_state = "computer"
|
||||
program_icon_state = "bountyboard"
|
||||
extended_desc = "This program allows any user to access the Newscaster network from anywhere."
|
||||
size = 2
|
||||
requires_ntnet = TRUE
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/datum/computer_file/program/notepad
|
||||
filename = "notepad"
|
||||
filedesc = "Notepad"
|
||||
category = PROGRAM_CATEGORY_MISC
|
||||
program_icon_state = "generic"
|
||||
extended_desc = "Jot down your work-safe thoughts and what not."
|
||||
size = 2
|
||||
tgui_id = "NtosNotepad"
|
||||
program_icon = "book"
|
||||
usage_flags = PROGRAM_TABLET
|
||||
|
||||
/datum/computer_file/program/notepad/ui_act(action, list/params, datum/tgui/ui)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
switch(action)
|
||||
if("UpdateNote")
|
||||
var/obj/item/modular_computer/tablet/comp = computer
|
||||
comp.note = params["newnote"]
|
||||
return UI_UPDATE
|
||||
|
||||
/datum/computer_file/program/notepad/ui_data(mob/user)
|
||||
var/list/data = get_header_data()
|
||||
var/obj/item/modular_computer/tablet/comp = computer
|
||||
|
||||
data["note"] = comp.note
|
||||
|
||||
return data
|
||||
@@ -0,0 +1,366 @@
|
||||
/datum/computer_file/program/messenger
|
||||
filename = "nt_messenger"
|
||||
filedesc = "Direct Messenger"
|
||||
category = PROGRAM_CATEGORY_MISC
|
||||
program_icon_state = "command"
|
||||
extended_desc = "This program allows old-school communication with other modular devices."
|
||||
size = 8
|
||||
usage_flags = PROGRAM_TABLET
|
||||
ui_header = "ntnrc_idle.gif"
|
||||
available_on_ntnet = TRUE
|
||||
tgui_id = "NtosMessenger"
|
||||
program_icon = "comment-alt"
|
||||
alert_able = TRUE
|
||||
|
||||
/// The current ringtone (displayed in the chat when a message is received).
|
||||
var/ringtone = "beep"
|
||||
/// Whether or not the ringtone is currently on.
|
||||
var/ringer_status = TRUE
|
||||
/// Whether or not we're sending and receiving messages.
|
||||
var/sending_and_receiving = TRUE
|
||||
/// The messages currently saved in the app.
|
||||
var/messages = list()
|
||||
/// great wisdom from PDA.dm - "no spamming" (prevents people from spamming the same message over and over)
|
||||
var/last_text
|
||||
/// even more wisdom from PDA.dm - "no everyone spamming" (prevents people from spamming the same message over and over)
|
||||
var/last_text_everyone
|
||||
/// Scanned photo for sending purposes.
|
||||
var/datum/picture/picture
|
||||
/// Whether or not we allow emojis to be sent by the user.
|
||||
var/allow_emojis = FALSE
|
||||
/// Whether or not we're currently looking at the message list.
|
||||
var/viewing_messages = FALSE
|
||||
// Whether or not this device is currently hidden from the message monitor.
|
||||
var/monitor_hidden = FALSE
|
||||
// Whether or not we're sorting by job.
|
||||
var/sort_by_job = TRUE
|
||||
// Whether or not we're sending (or trying to send) a virus.
|
||||
var/sending_virus = FALSE
|
||||
|
||||
/// The path for the current loaded image in rsc
|
||||
var/photo_path
|
||||
|
||||
/// Whether or not this app is loaded on a silicon's tablet.
|
||||
var/is_silicon = FALSE
|
||||
/// Whether or not we're in a mime PDA.
|
||||
var/mime_mode = FALSE
|
||||
|
||||
/datum/computer_file/program/messenger/proc/ScrubMessengerList()
|
||||
var/list/dictionary = list()
|
||||
|
||||
for(var/obj/item/modular_computer/messenger in GetViewableDevices(sort_by_job))
|
||||
if(messenger.saved_identification && messenger.saved_job && !(messenger == computer))
|
||||
var/list/data = list()
|
||||
data["name"] = messenger.saved_identification
|
||||
data["job"] = messenger.saved_job
|
||||
data["ref"] = REF(messenger)
|
||||
|
||||
//if(data["ref"] != REF(computer)) // you cannot message yourself (despite all my rage)
|
||||
dictionary += list(data)
|
||||
|
||||
return dictionary
|
||||
|
||||
/proc/GetViewableDevices(sort_by_job = FALSE)
|
||||
var/list/dictionary = list()
|
||||
|
||||
var/sortmode
|
||||
if(sort_by_job)
|
||||
sortmode = /proc/cmp_pdajob_asc
|
||||
else
|
||||
sortmode = /proc/cmp_pdaname_asc
|
||||
|
||||
for(var/obj/item/modular_computer/P in sort_list(GLOB.TabletMessengers, sortmode))
|
||||
var/obj/item/computer_hardware/hard_drive/drive = P.all_components[MC_HDD]
|
||||
if(!drive)
|
||||
continue
|
||||
for(var/datum/computer_file/program/messenger/app in drive.stored_files)
|
||||
if(!P.saved_identification || !P.saved_job || P.invisible || app.monitor_hidden)
|
||||
continue
|
||||
dictionary += P
|
||||
|
||||
return dictionary
|
||||
|
||||
/datum/computer_file/program/messenger/proc/StringifyMessengerTarget(obj/item/modular_computer/messenger)
|
||||
return "[messenger.saved_identification] ([messenger.saved_job])"
|
||||
|
||||
/datum/computer_file/program/messenger/proc/ProcessPhoto()
|
||||
if(computer.saved_image)
|
||||
var/icon/img = computer.saved_image.picture_image
|
||||
var/deter_path = "tmp_msg_photo[rand(0, 99999)].png"
|
||||
usr << browse_rsc(img, deter_path) // funny random assignment for now, i'll make an actual key later
|
||||
photo_path = deter_path
|
||||
|
||||
/datum/computer_file/program/messenger/ui_state(mob/user)
|
||||
if(istype(user, /mob/living/silicon))
|
||||
return GLOB.reverse_contained_state
|
||||
return GLOB.default_state
|
||||
|
||||
/datum/computer_file/program/messenger/ui_act(action, list/params, datum/tgui/ui)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
switch(action)
|
||||
if("PDA_ringSet")
|
||||
var/t = tgui_input_text(usr, "Enter a new tablet ID", "Computer ID", "", 20)
|
||||
var/mob/living/usr_mob = usr
|
||||
if(in_range(computer, usr_mob) && computer.loc == usr_mob && t)
|
||||
if(SEND_SIGNAL(computer, COMSIG_TABLET_CHANGE_ID, usr_mob, t) & COMPONENT_STOP_RINGTONE_CHANGE)
|
||||
return
|
||||
else
|
||||
ringtone = t
|
||||
return(UI_UPDATE)
|
||||
if("PDA_ringer_status")
|
||||
ringer_status = !ringer_status
|
||||
return(UI_UPDATE)
|
||||
if("PDA_sAndR")
|
||||
sending_and_receiving = !sending_and_receiving
|
||||
return(UI_UPDATE)
|
||||
if("PDA_viewMessages")
|
||||
viewing_messages = !viewing_messages
|
||||
return(UI_UPDATE)
|
||||
if("PDA_clearMessages")
|
||||
messages = list()
|
||||
return(UI_UPDATE)
|
||||
if("PDA_changeSortStyle")
|
||||
sort_by_job = !sort_by_job
|
||||
return(UI_UPDATE)
|
||||
if("PDA_sendEveryone")
|
||||
if(!sending_and_receiving)
|
||||
to_chat(usr, span_notice("ERROR: Device has sending disabled."))
|
||||
return
|
||||
|
||||
var/list/targets = list()
|
||||
|
||||
for(var/obj/item/modular_computer/mc in GetViewableDevices())
|
||||
targets += mc
|
||||
|
||||
if(targets.len > 0)
|
||||
send_message(usr, targets, TRUE)
|
||||
|
||||
return(UI_UPDATE)
|
||||
if("PDA_sendMessage")
|
||||
if(!sending_and_receiving)
|
||||
to_chat(usr, span_notice("ERROR: Device has sending disabled."))
|
||||
return
|
||||
var/obj/item/modular_computer/target = locate(params["ref"])
|
||||
if(!target)
|
||||
return // we don't want tommy sending his messages to nullspace
|
||||
if(!(target.saved_identification == params["name"] && target.saved_job == params["job"]))
|
||||
to_chat(usr, span_notice("ERROR: User no longer exists."))
|
||||
return
|
||||
|
||||
var/obj/item/computer_hardware/hard_drive/drive = target.all_components[MC_HDD]
|
||||
|
||||
for(var/datum/computer_file/program/messenger/app in drive.stored_files)
|
||||
if(!app.sending_and_receiving && !sending_virus)
|
||||
to_chat(usr, span_notice("ERROR: Device has receiving disabled."))
|
||||
return
|
||||
if(sending_virus)
|
||||
var/obj/item/computer_hardware/hard_drive/role/virus/disk = computer.all_components[MC_HDD_JOB]
|
||||
if(istype(disk))
|
||||
disk.send_virus(target, usr)
|
||||
return(UI_UPDATE)
|
||||
send_message(usr, list(target))
|
||||
return(UI_UPDATE)
|
||||
if("PDA_clearPhoto")
|
||||
computer.saved_image = null
|
||||
photo_path = null
|
||||
return(UI_UPDATE)
|
||||
if("PDA_toggleVirus")
|
||||
sending_virus = !sending_virus
|
||||
return(UI_UPDATE)
|
||||
|
||||
|
||||
/datum/computer_file/program/messenger/ui_data(mob/user)
|
||||
var/list/data = get_header_data()
|
||||
|
||||
var/obj/item/computer_hardware/hard_drive/role/disk = computer.all_components[MC_HDD_JOB]
|
||||
|
||||
data["owner"] = computer.saved_identification
|
||||
data["messages"] = messages
|
||||
data["ringer_status"] = ringer_status
|
||||
data["sending_and_receiving"] = sending_and_receiving
|
||||
data["messengers"] = ScrubMessengerList()
|
||||
data["viewing_messages"] = viewing_messages
|
||||
data["sortByJob"] = sort_by_job
|
||||
data["isSilicon"] = is_silicon
|
||||
data["photo"] = photo_path
|
||||
|
||||
if(disk)
|
||||
data["canSpam"] = disk.CanSpam()
|
||||
data["virus_attach"] = istype(disk, /obj/item/computer_hardware/hard_drive/role/virus)
|
||||
data["sending_virus"] = sending_virus
|
||||
|
||||
return data
|
||||
|
||||
////////////////////////
|
||||
// MESSAGE HANDLING
|
||||
////////////////////////
|
||||
|
||||
// How I Learned To Stop Being A PDA Bloat Chump And Learn To Embrace The Lightweight
|
||||
|
||||
// Gets the input for a message being sent.
|
||||
|
||||
/datum/computer_file/program/messenger/proc/msg_input(mob/living/U = usr, rigged = FALSE)
|
||||
var/t = null
|
||||
|
||||
if(mime_mode)
|
||||
t = emoji_sanitize(tgui_input_text(U, "Enter emojis", "NT Messaging"))
|
||||
else
|
||||
t = tgui_input_text(U, "Enter a message", "NT Messaging")
|
||||
|
||||
if (!t || !sending_and_receiving)
|
||||
return
|
||||
if(!U.canUseTopic(computer, BE_CLOSE))
|
||||
return
|
||||
return sanitize(t)
|
||||
|
||||
/datum/computer_file/program/messenger/proc/send_message(mob/living/user, list/obj/item/modular_computer/targets, everyone = FALSE, rigged = FALSE, fake_name = null, fake_job = null)
|
||||
var/message = msg_input(user, rigged)
|
||||
if(!message || !targets.len)
|
||||
return FALSE
|
||||
if((last_text && world.time < last_text + 10) || (everyone && last_text_everyone && world.time < last_text_everyone + 2 MINUTES))
|
||||
return FALSE
|
||||
|
||||
var/turf/position = get_turf(computer)
|
||||
for(var/obj/item/jammer/jammer as anything in GLOB.active_jammers)
|
||||
var/turf/jammer_turf = get_turf(jammer)
|
||||
if(position?.z == jammer_turf.z && (get_dist(position, jammer_turf) <= jammer.range))
|
||||
return FALSE
|
||||
|
||||
var/list/filter_result = CAN_BYPASS_FILTER(user) ? null : is_ic_filtered_for_pdas(message)
|
||||
if (filter_result)
|
||||
REPORT_CHAT_FILTER_TO_USER(user, filter_result)
|
||||
return FALSE
|
||||
|
||||
var/list/soft_filter_result = CAN_BYPASS_FILTER(user) ? null : is_soft_ic_filtered_for_pdas(message)
|
||||
if (soft_filter_result)
|
||||
if(tgui_alert(usr,"Your message contains \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\". \"[soft_filter_result[CHAT_FILTER_INDEX_REASON]]\", Are you sure you want to send it?", "Soft Blocked Word", list("Yes", "No")) != "Yes")
|
||||
return FALSE
|
||||
message_admins("[ADMIN_LOOKUPFLW(usr)] has passed the soft filter for \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\" they may be using a disallowed term in PDA messages. Message: \"[html_encode(message)]\"")
|
||||
log_admin_private("[key_name(usr)] has passed the soft filter for \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\" they may be using a disallowed term in PDA messages. Message: \"[message]\"")
|
||||
|
||||
// Send the signal
|
||||
var/list/string_targets = list()
|
||||
for (var/obj/item/modular_computer/comp in targets)
|
||||
if (comp.saved_identification && comp.saved_job) // != src is checked by the UI
|
||||
string_targets += STRINGIFY_PDA_TARGET(comp.saved_identification, comp.saved_job)
|
||||
|
||||
if (!string_targets.len)
|
||||
return FALSE
|
||||
|
||||
var/datum/signal/subspace/messaging/tablet_msg/signal = new(computer, list(
|
||||
"name" = fake_name || computer.saved_identification,
|
||||
"job" = fake_job || computer.saved_job,
|
||||
"message" = html_decode(message),
|
||||
"ref" = REF(computer),
|
||||
"targets" = targets,
|
||||
"emojis" = allow_emojis,
|
||||
"rigged" = rigged,
|
||||
"photo" = photo_path,
|
||||
"automated" = FALSE,
|
||||
))
|
||||
if(rigged) //Will skip the message server and go straight to the hub so it can't be cheesed by disabling the message server machine
|
||||
signal.data["rigged_user"] = REF(user) // Used for bomb logging
|
||||
signal.server_type = /obj/machinery/telecomms/hub
|
||||
signal.data["reject"] = FALSE // Do not refuse the message
|
||||
|
||||
signal.send_to_receivers()
|
||||
|
||||
// If it didn't reach, note that fact
|
||||
if (!signal.data["done"])
|
||||
to_chat(user, span_notice("ERROR: Server isn't responding."))
|
||||
//if(!silent)
|
||||
//playsound(src, 'sound/machines/terminal_error.ogg', 15, TRUE)
|
||||
return FALSE
|
||||
|
||||
if(allow_emojis)
|
||||
message = emoji_parse(message)//already sent- this just shows the sent emoji as one to the sender in the to_chat
|
||||
signal.data["message"] = emoji_parse(signal.data["message"])
|
||||
|
||||
// Log it in our logs
|
||||
var/list/message_data = list()
|
||||
message_data["name"] = signal.data["name"]
|
||||
message_data["job"] = signal.data["job"]
|
||||
message_data["contents"] = html_decode(signal.data["message"])
|
||||
message_data["outgoing"] = TRUE
|
||||
message_data["ref"] = signal.data["ref"]
|
||||
message_data["photo"] = signal.data["photo"]
|
||||
|
||||
// Show it to ghosts
|
||||
var/ghost_message = span_name("[message_data["name"]] </span><span class='game say'>[rigged ? "Rigged" : ""] PDA Message</span> --> [span_name("[signal.format_target()]")]: <span class='message'>[signal.data["message"]]")
|
||||
for(var/mob/M in GLOB.player_list)
|
||||
if(isobserver(M) && (M.client?.prefs.chat_toggles & CHAT_GHOSTPDA))
|
||||
to_chat(M, "[FOLLOW_LINK(M, user)] [ghost_message]")
|
||||
|
||||
// Log in the talk log
|
||||
user.log_talk(message, LOG_PDA, tag="[rigged ? "Rigged" : ""] PDA: [initial(message_data["name"])] to [signal.format_target()]")
|
||||
if(rigged)
|
||||
log_bomber(user, "sent a rigged PDA message (Name: [message_data["name"]]. Job: [message_data["job"]]) to [english_list(string_targets)] [!is_special_character(user) ? "(SENT BY NON-ANTAG)" : ""]")
|
||||
to_chat(user, span_info("PDA message sent to [signal.format_target()]: [signal.data["message"]]"))
|
||||
|
||||
if (ringer_status)
|
||||
computer.send_sound()
|
||||
|
||||
last_text = world.time
|
||||
if (everyone)
|
||||
message_data["name"] = "Everyone"
|
||||
message_data["job"] = ""
|
||||
last_text_everyone = world.time
|
||||
|
||||
messages += list(message_data)
|
||||
return TRUE
|
||||
|
||||
/datum/computer_file/program/messenger/proc/receive_message(datum/signal/subspace/messaging/tablet_msg/signal)
|
||||
var/list/message_data = list()
|
||||
message_data["name"] = signal.data["name"]
|
||||
message_data["job"] = signal.data["job"]
|
||||
message_data["contents"] = html_decode(signal.data["message"])
|
||||
message_data["outgoing"] = FALSE
|
||||
message_data["ref"] = signal.data["ref"]
|
||||
message_data["automated"] = signal.data["automated"]
|
||||
message_data["photo"] = signal.data["photo"]
|
||||
messages += list(message_data)
|
||||
|
||||
var/mob/living/L = null
|
||||
if(computer.loc && isliving(computer.loc))
|
||||
L = computer.loc
|
||||
//Maybe they are a pAI!
|
||||
else
|
||||
L = get(computer, /mob/living/silicon)
|
||||
|
||||
if(L && (L.stat == CONSCIOUS || L.stat == SOFT_CRIT))
|
||||
var/reply = "(<a href='byond://?src=[REF(src)];choice=[signal.data["rigged"] ? "Mess_us_up" : "Message"];skiprefresh=1;target=[signal.data["ref"]]'>Reply</a>)"
|
||||
var/hrefstart
|
||||
var/hrefend
|
||||
if (isAI(L))
|
||||
hrefstart = "<a href='?src=[REF(L)];track=[html_encode(signal.data["name"])]'>"
|
||||
hrefend = "</a>"
|
||||
|
||||
if(signal.data["automated"])
|
||||
reply = "\[Automated Message\]"
|
||||
|
||||
var/inbound_message = signal.format_message()
|
||||
if(signal.data["emojis"] == TRUE)//so will not parse emojis as such from pdas that don't send emojis
|
||||
inbound_message = emoji_parse(inbound_message)
|
||||
|
||||
if(ringer_status)
|
||||
to_chat(L, "<span class='infoplain'>[icon2html(src)] <b>PDA message from [hrefstart][signal.data["name"]] ([signal.data["job"]])[hrefend], </b>[inbound_message] [reply]</span>")
|
||||
|
||||
|
||||
if (ringer_status)
|
||||
computer.ring(ringtone)
|
||||
|
||||
/datum/computer_file/program/messenger/Topic(href, href_list)
|
||||
..()
|
||||
|
||||
if(!href_list["close"] && usr.canUseTopic(computer, BE_CLOSE, FALSE, NO_TK))
|
||||
switch(href_list["choice"])
|
||||
if("Message")
|
||||
send_message(usr, list(locate(href_list["target"])))
|
||||
if("Mess_us_up")
|
||||
if(!HAS_TRAIT(src, TRAIT_PDA_CAN_EXPLODE))
|
||||
var/obj/item/modular_computer/tablet/comp = computer
|
||||
comp.explode(usr, from_message_menu = TRUE)
|
||||
return
|
||||
@@ -0,0 +1,78 @@
|
||||
/datum/computer_file/program/phys_scanner
|
||||
filename = "phys_scanner"
|
||||
filedesc = "Physical Scanner"
|
||||
category = PROGRAM_CATEGORY_MISC
|
||||
extended_desc = "This program allows the tablet to scan physical objects and display a data output."
|
||||
size = 8
|
||||
usage_flags = PROGRAM_TABLET
|
||||
available_on_ntnet = FALSE
|
||||
tgui_id = "NtosPhysScanner"
|
||||
program_icon = "barcode"
|
||||
|
||||
var/current_mode = 0
|
||||
var/available_modes = 0
|
||||
|
||||
var/last_record = ""
|
||||
|
||||
/datum/computer_file/program/phys_scanner/proc/ReadModes()
|
||||
var/reads = list()
|
||||
|
||||
if(available_modes & DISK_CHEM)
|
||||
reads += "Reagent"
|
||||
|
||||
if(available_modes & DISK_MED)
|
||||
reads += "Health"
|
||||
|
||||
return reads
|
||||
|
||||
/datum/computer_file/program/phys_scanner/proc/ReadCurrent()
|
||||
if(current_mode & DISK_CHEM)
|
||||
return "Reagent"
|
||||
if(current_mode & DISK_MED)
|
||||
return "Health"
|
||||
|
||||
/datum/computer_file/program/phys_scanner/tap(atom/A, mob/living/user, params)
|
||||
. = ..()
|
||||
|
||||
switch(current_mode)
|
||||
if(DISK_CHEM)
|
||||
if(!isnull(A.reagents))
|
||||
if(A.reagents.reagent_list.len > 0)
|
||||
var/reagents_length = A.reagents.reagent_list.len
|
||||
last_record = "[reagents_length] chemical agent[reagents_length > 1 ? "s" : ""] found."
|
||||
for (var/re in A.reagents.reagent_list)
|
||||
last_record += "\t [re]"
|
||||
else
|
||||
last_record = "No active chemical agents found in [A]."
|
||||
else
|
||||
last_record = "No significant chemical agents found in [A]."
|
||||
if(DISK_MED)
|
||||
var/mob/living/carbon/carbon = A
|
||||
if(istype(carbon))
|
||||
carbon.visible_message(span_notice("[user] analyzes [A]'s vitals."))
|
||||
last_record = healthscan(user, carbon, 1, tochat = FALSE)
|
||||
|
||||
/datum/computer_file/program/phys_scanner/ui_act(action, list/params, datum/tgui/ui)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
switch(action)
|
||||
if("selectMode")
|
||||
switch(params["newMode"])
|
||||
if("Reagent")
|
||||
current_mode = DISK_CHEM
|
||||
if("Health")
|
||||
current_mode = DISK_MED
|
||||
|
||||
return UI_UPDATE
|
||||
|
||||
|
||||
/datum/computer_file/program/phys_scanner/ui_data(mob/user)
|
||||
var/list/data = get_header_data()
|
||||
|
||||
data["set_mode"] = ReadCurrent()
|
||||
data["last_record"] = last_record
|
||||
data["available_modes"] = ReadModes()
|
||||
|
||||
return data
|
||||
@@ -0,0 +1,74 @@
|
||||
/datum/computer_file/program/records
|
||||
filename = "ntrecords"
|
||||
filedesc = "Records"
|
||||
extended_desc = "Allows the user to view several basic records from the crew."
|
||||
category = PROGRAM_CATEGORY_MISC
|
||||
program_icon = "clipboard"
|
||||
program_icon_state = "crew"
|
||||
tgui_id = "NtosRecords"
|
||||
size = 4
|
||||
usage_flags = PROGRAM_TABLET | PROGRAM_LAPTOP
|
||||
available_on_ntnet = FALSE
|
||||
|
||||
var/mode
|
||||
|
||||
/datum/computer_file/program/records/medical
|
||||
filedesc = "Medical Records"
|
||||
filename = "medrecords"
|
||||
program_icon = "book-medical"
|
||||
extended_desc = "Allows the user to view several basic medical records from the crew."
|
||||
transfer_access = list(ACCESS_MEDICAL, ACCESS_FLAG_COMMAND)
|
||||
available_on_ntnet = TRUE
|
||||
mode = "medical"
|
||||
|
||||
/datum/computer_file/program/records/security
|
||||
filedesc = "Security Records"
|
||||
filename = "secrecords"
|
||||
extended_desc = "Allows the user to view several basic security records from the crew."
|
||||
transfer_access = list(ACCESS_SECURITY, ACCESS_FLAG_COMMAND)
|
||||
available_on_ntnet = TRUE
|
||||
mode = "security"
|
||||
|
||||
/datum/computer_file/program/records/proc/GetRecordsReadable()
|
||||
var/list/all_records = list()
|
||||
|
||||
switch(mode)
|
||||
if("security")
|
||||
for(var/datum/data/record/person in GLOB.data_core.general)
|
||||
var/datum/data/record/security_person = find_record("id", person.fields["id"], GLOB.data_core.security)
|
||||
var/list/current_record = list()
|
||||
|
||||
if(security_person)
|
||||
current_record["wanted"] = security_person.fields["criminal"]
|
||||
|
||||
current_record["id"] = person.fields["id"]
|
||||
current_record["name"] = person.fields["name"]
|
||||
current_record["rank"] = person.fields["rank"]
|
||||
current_record["gender"] = person.fields["gender"]
|
||||
current_record["age"] = person.fields["age"]
|
||||
current_record["species"] = person.fields["species"]
|
||||
current_record["fingerprint"] = person.fields["fingerprint"]
|
||||
|
||||
all_records += list(current_record)
|
||||
if("medical")
|
||||
for(var/datum/data/record/person in GLOB.data_core.medical)
|
||||
var/list/current_record = list()
|
||||
|
||||
current_record["name"] = person.fields["name"]
|
||||
current_record["bloodtype"] = person.fields["blood_type"]
|
||||
current_record["mi_dis"] = person.fields["mi_dis"]
|
||||
current_record["ma_dis"] = person.fields["ma_dis"]
|
||||
current_record["notes"] = person.fields["notes"]
|
||||
current_record["cnotes"] = person.fields["notes_d"]
|
||||
|
||||
all_records += list(current_record)
|
||||
|
||||
return all_records
|
||||
|
||||
|
||||
|
||||
/datum/computer_file/program/records/ui_data(mob/user)
|
||||
var/list/data = get_header_data()
|
||||
data["records"] = GetRecordsReadable()
|
||||
data["mode"] = mode
|
||||
return data
|
||||
@@ -13,6 +13,8 @@
|
||||
var/botcount = 0
|
||||
///Access granted by the used to summon robots.
|
||||
var/list/current_access = list()
|
||||
///Whether or not this is the cartridge program version.
|
||||
var/cart_mode = FALSE
|
||||
var/list/drone_ping_types = list(
|
||||
"Low",
|
||||
"Medium",
|
||||
@@ -27,20 +29,23 @@
|
||||
var/list/botlist = list()
|
||||
var/list/mulelist = list()
|
||||
|
||||
var/obj/item/computer_hardware/hard_drive/role/job_disk = computer ? computer.all_components[MC_HDD_JOB] : null
|
||||
var/obj/item/computer_hardware/card_slot/card_slot = computer ? computer.all_components[MC_CARD] : null
|
||||
var/obj/item/card/id/id_card = card_slot?.stored_card
|
||||
data["have_id_slot"] = !!card_slot
|
||||
if(computer)
|
||||
data["has_id"] = !!id_card
|
||||
data["id_owner"] = id_card ? id_card.registered_name : "No Card Inserted."
|
||||
data["access_on_card"] = id_card ? id_card.access : null
|
||||
var/obj/item/card/id/id_card = card_slot ? card_slot.stored_card : ""
|
||||
data["id_owner"] = id_card
|
||||
if(cart_mode && job_disk)
|
||||
data["id_owner"] = "JOB DISK OVERRIDE"
|
||||
|
||||
botcount = 0
|
||||
|
||||
for(var/mob/living/simple_animal/bot/simple_bot as anything in GLOB.bots_list)
|
||||
if(simple_bot.z != zlevel || !(simple_bot.bot_mode_flags & BOT_MODE_REMOTE_ENABLED)) //Only non-emagged bots on the same Z-level are detected!
|
||||
continue
|
||||
if(computer && !simple_bot.check_access(user, id_card)) // Only check Bots we can access
|
||||
if(computer && !simple_bot.check_access(user) && !cart_mode) // Only check Bots we can access)
|
||||
continue
|
||||
if(!(simple_bot.bot_type in job_disk.bot_access) && cart_mode)
|
||||
continue
|
||||
var/list/newbot = list(
|
||||
"name" = simple_bot.name,
|
||||
|
||||
@@ -19,14 +19,16 @@
|
||||
. = ..()
|
||||
if (!.)
|
||||
return
|
||||
if(!computer?.get_modular_computer_part(MC_SIGNALER)) //Giving a clue to users why the program is spitting out zeros.
|
||||
var/obj/item/computer_hardware/hard_drive/role/signal/disk = computer?.get_modular_computer_part(MC_HDD_JOB)
|
||||
if(!(computer?.get_modular_computer_part(MC_SIGNALER) || istype(disk))) //Giving a clue to users why the program is spitting out zeros.
|
||||
to_chat(user, span_warning("\The [computer] flashes an error: \"hardware\\signal_hardware\\startup.bin -- file not found\"."))
|
||||
|
||||
|
||||
/datum/computer_file/program/signaler/ui_data(mob/user)
|
||||
var/list/data = get_header_data()
|
||||
var/obj/item/computer_hardware/radio_card/sensor = computer?.get_modular_computer_part(MC_SIGNALER)
|
||||
if(sensor?.check_functionality())
|
||||
var/obj/item/computer_hardware/hard_drive/role/signal/disk = computer?.get_modular_computer_part(MC_HDD_JOB)
|
||||
if(sensor?.check_functionality() || istype(disk))
|
||||
data["frequency"] = signal_frequency
|
||||
data["code"] = signal_code
|
||||
data["minFrequency"] = MIN_FREE_FREQ
|
||||
@@ -38,7 +40,8 @@
|
||||
if(.)
|
||||
return
|
||||
var/obj/item/computer_hardware/radio_card/sensor = computer?.get_modular_computer_part(MC_SIGNALER)
|
||||
if(!(sensor?.check_functionality()))
|
||||
var/obj/item/computer_hardware/hard_drive/role/signal/disk = computer?.get_modular_computer_part(MC_HDD_JOB)
|
||||
if(!(sensor?.check_functionality() || istype(disk)))
|
||||
playsound(src, 'sound/machines/scanbuzz.ogg', 100, FALSE)
|
||||
return
|
||||
switch(action)
|
||||
@@ -65,18 +68,19 @@
|
||||
return
|
||||
|
||||
var/time = time2text(world.realtime,"hh:mm:ss")
|
||||
var/turf/T = get_turf(src)
|
||||
var/turf/T = get_turf(computer)
|
||||
|
||||
var/logging_data
|
||||
if(usr)
|
||||
logging_data = "[time] <B>:</B> [usr.key] used [src] @ location ([T.x],[T.y],[T.z]) <B>:</B> [format_frequency(signal_frequency)]/[signal_code]"
|
||||
message_admins("usr is true")
|
||||
logging_data = "[time] <B>:</B> [usr.key] used [computer] @ location ([T.x],[T.y],[T.z]) <B>:</B> [format_frequency(signal_frequency)]/[signal_code]"
|
||||
GLOB.lastsignalers.Add(logging_data)
|
||||
|
||||
var/datum/signal/signal = new(list("code" = signal_code), logging_data = logging_data)
|
||||
radio_connection.post_signal(src, signal)
|
||||
radio_connection.post_signal(computer, signal)
|
||||
|
||||
/datum/computer_file/program/signaler/proc/set_frequency(new_frequency)
|
||||
SSradio.remove_object(src, signal_frequency)
|
||||
SSradio.remove_object(computer, signal_frequency)
|
||||
signal_frequency = new_frequency
|
||||
radio_connection = SSradio.add_object(src, signal_frequency, RADIO_SIGNALER)
|
||||
radio_connection = SSradio.add_object(computer, signal_frequency, RADIO_SIGNALER)
|
||||
return
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/datum/computer_file/program/status
|
||||
filename = "statusdisplay"
|
||||
filedesc = "Status Display"
|
||||
program_icon = "signal"
|
||||
program_icon_state = "generic"
|
||||
requires_ntnet = TRUE
|
||||
size = 4
|
||||
|
||||
extended_desc = "An app used to change the message on the station status displays."
|
||||
tgui_id = "NtosStatus"
|
||||
|
||||
usage_flags = PROGRAM_ALL
|
||||
available_on_ntnet = FALSE
|
||||
|
||||
var/upper_text
|
||||
var/lower_text
|
||||
|
||||
/datum/computer_file/program/status/proc/SendSignal()
|
||||
var/datum/radio_frequency/frequency = SSradio.return_frequency(FREQ_STATUS_DISPLAYS)
|
||||
|
||||
if(!frequency)
|
||||
return
|
||||
|
||||
var/datum/signal/status_signal = new(list("command" = "message"))
|
||||
|
||||
status_signal.data["msg1"] = reject_bad_text(upper_text || "", MAX_STATUS_LINE_LENGTH)
|
||||
status_signal.data["msg2"] = reject_bad_text(lower_text || "", MAX_STATUS_LINE_LENGTH)
|
||||
|
||||
frequency.post_signal(computer, status_signal)
|
||||
|
||||
/datum/computer_file/program/status/proc/SetText(position, text)
|
||||
switch(position)
|
||||
if("upper")
|
||||
upper_text = text
|
||||
if("lower")
|
||||
lower_text = text
|
||||
|
||||
/datum/computer_file/program/status/ui_act(action, list/params, datum/tgui/ui)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
switch(action)
|
||||
if("stat_send")
|
||||
SendSignal()
|
||||
if("stat_update")
|
||||
SetText(params["position"], params["text"]) // i hate the player i hate the player
|
||||
|
||||
/datum/computer_file/program/status/ui_data(mob/user)
|
||||
var/list/data = get_header_data()
|
||||
|
||||
data["upper"] = upper_text
|
||||
data["lower"] = lower_text
|
||||
|
||||
return data
|
||||
@@ -7,6 +7,8 @@
|
||||
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)
|
||||
@@ -76,6 +78,10 @@
|
||||
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))
|
||||
@@ -99,6 +105,11 @@
|
||||
|
||||
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
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
var/max_capacity = 128
|
||||
var/used_capacity = 0
|
||||
var/list/stored_files = list() // List of stored files on this drive. DO NOT MODIFY DIRECTLY!
|
||||
var/default_installs = TRUE // install the default progs
|
||||
|
||||
/obj/item/computer_hardware/hard_drive/on_remove(obj/item/modular_computer/remove_from, mob/user)
|
||||
remove_from.shutdown_computer()
|
||||
@@ -130,7 +131,9 @@
|
||||
|
||||
/obj/item/computer_hardware/hard_drive/Initialize(mapload)
|
||||
. = ..()
|
||||
install_default_programs()
|
||||
|
||||
if(default_installs)
|
||||
install_default_programs()
|
||||
|
||||
|
||||
/obj/item/computer_hardware/hard_drive/advanced
|
||||
@@ -167,12 +170,25 @@
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
custom_price = PAYCHECK_MEDIUM * 2
|
||||
|
||||
/obj/item/computer_hardware/hard_drive/small/install_default_programs()
|
||||
. = ..()
|
||||
|
||||
store_file(new /datum/computer_file/program/messenger(src))
|
||||
store_file(new /datum/computer_file/program/notepad(src))
|
||||
|
||||
// For borg integrated tablets. No downloader.
|
||||
/obj/item/computer_hardware/hard_drive/small/integrated/install_default_programs()
|
||||
var/datum/computer_file/program/messenger/messenger = new(src)
|
||||
messenger.is_silicon = TRUE
|
||||
store_file(messenger)
|
||||
|
||||
/obj/item/computer_hardware/hard_drive/small/integrated/borg/install_default_programs()
|
||||
store_file(new /datum/computer_file/program/computerconfig(src)) // Computer configuration utility, allows hardware control and displays more info than status bar
|
||||
store_file(new /datum/computer_file/program/filemanager(src)) // File manager, allows text editor functions and basic file manipulation.
|
||||
store_file(new /datum/computer_file/program/robotact(src))
|
||||
|
||||
var/datum/computer_file/program/messenger/messenger = new(src)
|
||||
messenger.is_silicon = TRUE
|
||||
store_file(messenger)
|
||||
|
||||
// Syndicate variant - very slight better
|
||||
/obj/item/computer_hardware/hard_drive/small/syndicate
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
/obj/item/computer_hardware/identifier
|
||||
name = "identifier"
|
||||
desc = "Used to automatically update the names of modular devices."
|
||||
power_usage = 0
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
device_type = MC_IDENTIFY
|
||||
expansion_hw = FALSE
|
||||
|
||||
/obj/item/computer_hardware/identifier/proc/UpdateDisplay()
|
||||
var/name = holder.saved_identification
|
||||
var/job = holder.saved_job
|
||||
|
||||
holder.name = "[name] ([job])"
|
||||
@@ -0,0 +1,253 @@
|
||||
/obj/item/computer_hardware/hard_drive/role
|
||||
name = "job data disk"
|
||||
desc = "A disk meant to give a worker the needed programs to work."
|
||||
power_usage = 0
|
||||
icon_state = "datadisk6"
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
critical = FALSE
|
||||
max_capacity = 500
|
||||
device_type = MC_HDD_JOB
|
||||
default_installs = FALSE
|
||||
|
||||
var/disk_flags = 0 // bit flag for the programs
|
||||
var/can_spam = FALSE
|
||||
var/list/bot_access = list()
|
||||
|
||||
/obj/item/computer_hardware/hard_drive/role/on_remove(obj/item/modular_computer/remove_from, mob/user)
|
||||
return
|
||||
|
||||
/obj/item/computer_hardware/hard_drive/role/Initialize(mapload)
|
||||
. = ..()
|
||||
var/list/progs_to_store = list()
|
||||
|
||||
if(disk_flags & DISK_POWER)
|
||||
progs_to_store += new /datum/computer_file/program/power_monitor(src)
|
||||
progs_to_store += new /datum/computer_file/program/supermatter_monitor(src)
|
||||
|
||||
if(disk_flags & DISK_ATMOS)
|
||||
progs_to_store += new /datum/computer_file/program/atmosscan(src)
|
||||
|
||||
if(disk_flags & DISK_MANIFEST)
|
||||
progs_to_store += new /datum/computer_file/program/crew_manifest(src)
|
||||
|
||||
if(disk_flags & DISK_SEC)
|
||||
progs_to_store += new /datum/computer_file/program/records/security(src)
|
||||
|
||||
if(disk_flags & DISK_JANI)
|
||||
progs_to_store += new /datum/computer_file/program/radar/custodial_locator(src)
|
||||
|
||||
if((disk_flags & DISK_CHEM) || (disk_flags & DISK_MED))
|
||||
var/datum/computer_file/program/phys_scanner/scanner = new(src)
|
||||
|
||||
if(disk_flags & DISK_CHEM)
|
||||
scanner.available_modes += DISK_CHEM
|
||||
|
||||
if(disk_flags & DISK_MED)
|
||||
progs_to_store += new /datum/computer_file/program/records/medical(src)
|
||||
scanner.available_modes += DISK_MED
|
||||
|
||||
progs_to_store += scanner
|
||||
|
||||
if(disk_flags & DISK_ROBOS)
|
||||
var/datum/computer_file/program/robocontrol/robo = new(src)
|
||||
robo.cart_mode = TRUE
|
||||
progs_to_store += robo
|
||||
|
||||
if(disk_flags & DISK_CARGO)
|
||||
progs_to_store += new /datum/computer_file/program/shipping(src)
|
||||
|
||||
if(disk_flags & DISK_SIGNAL)
|
||||
progs_to_store += new /datum/computer_file/program/signaler(src)
|
||||
|
||||
if(disk_flags & DISK_NEWS)
|
||||
progs_to_store += new /datum/computer_file/program/newscaster(src)
|
||||
|
||||
if(disk_flags & DISK_BUDGET)
|
||||
progs_to_store += new /datum/computer_file/program/budgetorders(src)
|
||||
|
||||
if(disk_flags & DISK_STATUS)
|
||||
progs_to_store += new /datum/computer_file/program/status(src)
|
||||
|
||||
for (var/datum/computer_file/program/prog in progs_to_store)
|
||||
prog.usage_flags = PROGRAM_ALL
|
||||
prog.required_access = list()
|
||||
prog.transfer_access = list()
|
||||
store_file(prog)
|
||||
|
||||
|
||||
|
||||
/obj/item/computer_hardware/hard_drive/role/proc/CanSpam()
|
||||
return can_spam
|
||||
|
||||
// Disk Definitions
|
||||
|
||||
/obj/item/computer_hardware/hard_drive/role/engineering
|
||||
name = "Power-ON disk"
|
||||
desc = "Engineers ignoring station power-draw since 2400."
|
||||
icon_state = "datadisk2"
|
||||
disk_flags = DISK_POWER
|
||||
|
||||
/obj/item/computer_hardware/hard_drive/role/atmos
|
||||
name = "\improper BreatheDeep disk"
|
||||
icon_state = "datadisk2"
|
||||
disk_flags = DISK_ATMOS | DISK_ROBOS
|
||||
bot_access = list(
|
||||
FLOOR_BOT,
|
||||
FIRE_BOT,
|
||||
)
|
||||
|
||||
/obj/item/computer_hardware/hard_drive/role/medical
|
||||
name = "\improper Med-U disk"
|
||||
icon_state = "datadisk7"
|
||||
disk_flags = DISK_MED | DISK_ROBOS
|
||||
bot_access = list(
|
||||
MED_BOT,
|
||||
)
|
||||
|
||||
/obj/item/computer_hardware/hard_drive/role/chemistry
|
||||
name = "\improper ChemWhiz disk"
|
||||
icon_state = "datadisk7"
|
||||
disk_flags = DISK_CHEM
|
||||
|
||||
/obj/item/computer_hardware/hard_drive/role/security
|
||||
name = "\improper R.O.B.U.S.T. disk"
|
||||
icon_state = "datadisk9"
|
||||
disk_flags = DISK_SEC | DISK_MANIFEST | DISK_ROBOS
|
||||
bot_access = list(
|
||||
SEC_BOT,
|
||||
ADVANCED_SEC_BOT,
|
||||
)
|
||||
|
||||
/obj/item/computer_hardware/hard_drive/role/detective
|
||||
name = "\improper D.E.T.E.C.T. disk"
|
||||
icon_state = "datadisk9"
|
||||
disk_flags = DISK_MED | DISK_SEC | DISK_MANIFEST | DISK_ROBOS
|
||||
bot_access = list(
|
||||
SEC_BOT,
|
||||
ADVANCED_SEC_BOT,
|
||||
)
|
||||
|
||||
/obj/item/computer_hardware/hard_drive/role/janitor
|
||||
name = "\improper CustodiPRO disk"
|
||||
icon_state = "datadisk5"
|
||||
desc = "The ultimate in clean-room design."
|
||||
disk_flags = DISK_JANI | DISK_ROBOS
|
||||
bot_access = list(
|
||||
CLEAN_BOT,
|
||||
)
|
||||
|
||||
/obj/item/computer_hardware/hard_drive/role/lawyer
|
||||
name = "\improper P.R.O.V.E. disk"
|
||||
icon_state = "datadisk9"
|
||||
disk_flags = DISK_SEC
|
||||
can_spam = TRUE
|
||||
|
||||
/obj/item/computer_hardware/hard_drive/role/curator
|
||||
name = "\improper Lib-Tweet disk"
|
||||
icon_state = "datadisk2"
|
||||
disk_flags = DISK_NEWS
|
||||
|
||||
/obj/item/computer_hardware/hard_drive/role/roboticist
|
||||
name = "\improper B.O.O.P. Remote Control disk"
|
||||
icon_state = "datadisk5"
|
||||
desc = "Packed with heavy duty quad-bot interlink!"
|
||||
disk_flags = DISK_ROBOS
|
||||
bot_access = list(
|
||||
FLOOR_BOT,
|
||||
CLEAN_BOT,
|
||||
MED_BOT,
|
||||
FIRE_BOT,
|
||||
VIBE_BOT,
|
||||
)
|
||||
|
||||
/obj/item/computer_hardware/hard_drive/role/signal
|
||||
name = "generic signaler disk"
|
||||
icon_state = "datadisk5"
|
||||
desc = "A data disk with an integrated radio signaler module."
|
||||
disk_flags = DISK_SIGNAL
|
||||
|
||||
/obj/item/computer_hardware/hard_drive/role/signal/ordnance
|
||||
name = "\improper Signal Ace 2 disk"
|
||||
icon_state = "datadisk5"
|
||||
desc = "Complete with integrated radio signaler!"
|
||||
disk_flags = DISK_ATMOS | DISK_SIGNAL | DISK_CHEM
|
||||
|
||||
/obj/item/computer_hardware/hard_drive/role/quartermaster
|
||||
name = "space parts & space vendors disk"
|
||||
icon_state = "datadisk0"
|
||||
desc = "Perfect for the Quartermaster on the go!"
|
||||
disk_flags = DISK_CARGO | DISK_ROBOS | DISK_BUDGET
|
||||
bot_access = list(
|
||||
MULE_BOT,
|
||||
)
|
||||
|
||||
/obj/item/computer_hardware/hard_drive/role/head
|
||||
name = "\improper Easy-Record DELUXE disk"
|
||||
icon_state = "datadisk7"
|
||||
disk_flags = DISK_MANIFEST | DISK_STATUS | DISK_BUDGET
|
||||
|
||||
/obj/item/computer_hardware/hard_drive/role/hop
|
||||
name = "\improper HumanResources9001 disk"
|
||||
icon_state = "datadisk7"
|
||||
disk_flags = DISK_MANIFEST | DISK_STATUS | DISK_JANI | DISK_SEC | DISK_NEWS | DISK_CARGO | DISK_ROBOS | DISK_BUDGET
|
||||
bot_access = list(
|
||||
MULE_BOT,
|
||||
CLEAN_BOT,
|
||||
VIBE_BOT,
|
||||
)
|
||||
|
||||
/obj/item/computer_hardware/hard_drive/role/hos
|
||||
name = "\improper R.O.B.U.S.T. DELUXE disk"
|
||||
icon_state = "datadisk7"
|
||||
disk_flags = DISK_MANIFEST | DISK_STATUS | DISK_SEC | DISK_ROBOS | DISK_BUDGET
|
||||
bot_access = list(
|
||||
SEC_BOT,
|
||||
ADVANCED_SEC_BOT,
|
||||
)
|
||||
|
||||
|
||||
/obj/item/computer_hardware/hard_drive/role/ce
|
||||
name = "\improper Power-On DELUXE disk"
|
||||
icon_state = "datadisk7"
|
||||
disk_flags = DISK_POWER | DISK_ATMOS | DISK_MANIFEST | DISK_STATUS | DISK_ROBOS | DISK_BUDGET
|
||||
bot_access = list(
|
||||
FLOOR_BOT,
|
||||
FIRE_BOT,
|
||||
)
|
||||
|
||||
/obj/item/computer_hardware/hard_drive/role/cmo
|
||||
name = "\improper Med-U DELUXE disk"
|
||||
icon_state = "datadisk7"
|
||||
disk_flags = DISK_MANIFEST | DISK_STATUS | DISK_CHEM | DISK_ROBOS | DISK_BUDGET
|
||||
bot_access = list(
|
||||
MED_BOT,
|
||||
)
|
||||
|
||||
/obj/item/computer_hardware/hard_drive/role/rd
|
||||
name = "\improper Signal Ace DELUXE disk"
|
||||
icon_state = "rndmajordisk"
|
||||
disk_flags = DISK_ATMOS | DISK_MANIFEST | DISK_STATUS | DISK_CHEM | DISK_ROBOS | DISK_BUDGET | DISK_SIGNAL
|
||||
bot_access = list(
|
||||
FLOOR_BOT,
|
||||
CLEAN_BOT,
|
||||
MED_BOT,
|
||||
FIRE_BOT,
|
||||
VIBE_BOT,
|
||||
)
|
||||
|
||||
/obj/item/computer_hardware/hard_drive/role/captain
|
||||
name = "\improper Value-PAK disk"
|
||||
icon_state = "datadisk8"
|
||||
desc = "Now with 350% more value!" //Give the Captain...EVERYTHING! (Except Mime, Clown, and Syndie)
|
||||
disk_flags = ~0
|
||||
can_spam = TRUE
|
||||
bot_access = list(
|
||||
SEC_BOT,
|
||||
ADVANCED_SEC_BOT,
|
||||
MULE_BOT,
|
||||
FLOOR_BOT,
|
||||
CLEAN_BOT,
|
||||
MED_BOT,
|
||||
FIRE_BOT,
|
||||
VIBE_BOT,
|
||||
)
|
||||
@@ -88,10 +88,12 @@
|
||||
if(!modularInterface.borgo)
|
||||
return FALSE //No borg found
|
||||
|
||||
if(modularInterface.borgo.lockcharge)
|
||||
return FALSE //lockdown restricts borg networking
|
||||
var/mob/living/silicon/robot/robo = modularInterface.borgo
|
||||
if(istype(robo))
|
||||
if(robo.lockcharge)
|
||||
return FALSE //lockdown restricts borg networking
|
||||
|
||||
if(!modularInterface.borgo.cell || modularInterface.borgo.cell.charge == 0)
|
||||
return FALSE //borg cell dying restricts borg networking
|
||||
if(!robo.cell || robo.cell.charge == 0)
|
||||
return FALSE //borg cell dying restricts borg networking
|
||||
|
||||
return ..()
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
/obj/item/computer_hardware/hard_drive/role/virus
|
||||
name = "\improper generic virus disk"
|
||||
icon_state = "virusdisk"
|
||||
var/charges = 5
|
||||
|
||||
/obj/item/computer_hardware/hard_drive/role/virus/proc/send_virus(obj/item/modular_computer/tablet/target, mob/living/user)
|
||||
return
|
||||
|
||||
/obj/item/computer_hardware/hard_drive/role/virus/clown
|
||||
name = "\improper H.O.N.K. disk"
|
||||
|
||||
/obj/item/computer_hardware/hard_drive/role/virus/clown/send_virus(obj/item/modular_computer/tablet/target, mob/living/user)
|
||||
if(charges <= 0)
|
||||
to_chat(user, span_notice("ERROR: Out of charges."))
|
||||
return
|
||||
|
||||
if(target)
|
||||
user.show_message(span_notice("Success!"))
|
||||
charges--
|
||||
target.honkamnt = rand(15, 25)
|
||||
else
|
||||
to_chat(user, span_notice("ERROR: Could not find device."))
|
||||
|
||||
/obj/item/computer_hardware/hard_drive/role/virus/mime
|
||||
name = "\improper sound of silence disk"
|
||||
|
||||
/obj/item/computer_hardware/hard_drive/role/virus/mime/send_virus(obj/item/modular_computer/tablet/target, mob/living/user)
|
||||
if(charges <= 0)
|
||||
to_chat(user, span_notice("ERROR: Out of charges."))
|
||||
return
|
||||
|
||||
if(target)
|
||||
user.show_message(span_notice("Success!"))
|
||||
charges--
|
||||
|
||||
var/obj/item/computer_hardware/hard_drive/drive = target.all_components[MC_HDD]
|
||||
|
||||
for(var/datum/computer_file/program/messenger/app in drive.stored_files)
|
||||
app.ringer_status = FALSE
|
||||
app.ringtone = ""
|
||||
else
|
||||
to_chat(user, span_notice("ERROR: Could not find device."))
|
||||
|
||||
/obj/item/computer_hardware/hard_drive/role/virus/deto
|
||||
name = "\improper D.E.T.O.M.A.T.I.X. disk"
|
||||
charges = 6
|
||||
|
||||
/obj/item/computer_hardware/hard_drive/role/virus/deto/send_virus(obj/item/modular_computer/tablet/target, mob/living/user)
|
||||
if(charges <= 0)
|
||||
to_chat(user, span_notice("ERROR: Out of charges."))
|
||||
return
|
||||
|
||||
var/difficulty = 0
|
||||
var/obj/item/computer_hardware/hard_drive/role/disk = target.all_components[MC_HDD_JOB]
|
||||
|
||||
if(disk)
|
||||
difficulty += bit_count(disk.disk_flags & (DISK_MED | DISK_SEC | DISK_POWER | DISK_MANIFEST))
|
||||
if(disk.disk_flags & DISK_MANIFEST)
|
||||
difficulty++ //if cartridge has manifest access it has extra snowflake difficulty
|
||||
if(SEND_SIGNAL(target, COMSIG_TABLET_CHECK_DETONATE) & COMPONENT_TABLET_NO_DETONATE || prob(difficulty * 15))
|
||||
user.show_message(span_danger("ERROR: Target could not be bombed."), MSG_VISUAL)
|
||||
charges--
|
||||
return
|
||||
|
||||
var/original_host = holder
|
||||
var/fakename = sanitize_name(tgui_input_text(user, "Enter a name for the rigged message.", "Forge Message", max_length = MAX_NAME_LEN), allow_numbers = TRUE)
|
||||
if(!fakename || holder != original_host || !user.canUseTopic(holder, BE_CLOSE))
|
||||
return
|
||||
var/fakejob = sanitize_name(tgui_input_text(user, "Enter a job for the rigged message.", "Forge Message", max_length = MAX_NAME_LEN), allow_numbers = TRUE)
|
||||
if(!fakejob || holder != original_host || !user.canUseTopic(holder, BE_CLOSE))
|
||||
return
|
||||
|
||||
var/obj/item/computer_hardware/hard_drive/drive = holder.all_components[MC_HDD]
|
||||
|
||||
for(var/datum/computer_file/program/messenger/app in drive.stored_files)
|
||||
if(charges > 0 && app.send_message(user, list(target), rigged = REF(user), fake_name = fakename, fake_job = fakejob))
|
||||
charges--
|
||||
user.show_message(span_notice("Success!"))
|
||||
var/reference = REF(src)
|
||||
ADD_TRAIT(target, TRAIT_PDA_CAN_EXPLODE, reference)
|
||||
ADD_TRAIT(target, TRAIT_PDA_MESSAGE_MENU_RIGGED, reference)
|
||||
addtimer(TRAIT_CALLBACK_REMOVE(target, TRAIT_PDA_MESSAGE_MENU_RIGGED, reference), 10 SECONDS)
|
||||
|
||||
/obj/item/computer_hardware/hard_drive/role/virus/frame
|
||||
name = "\improper F.R.A.M.E. disk"
|
||||
|
||||
var/telecrystals = 0
|
||||
var/current_progression = 0
|
||||
|
||||
/obj/item/computer_hardware/hard_drive/role/virus/frame/send_virus(obj/item/modular_computer/tablet/target, mob/living/user)
|
||||
if(charges <= 0)
|
||||
to_chat(user, span_notice("ERROR: Out of charges."))
|
||||
return
|
||||
|
||||
if(target)
|
||||
charges--
|
||||
var/lock_code = "[rand(100,999)] [pick(GLOB.phonetic_alphabet)]"
|
||||
to_chat(user, span_notice("Success! The unlock code to the target is: [lock_code]"))
|
||||
var/datum/component/uplink/hidden_uplink = target.GetComponent(/datum/component/uplink)
|
||||
if(!hidden_uplink)
|
||||
var/datum/mind/target_mind
|
||||
var/list/backup_players = list()
|
||||
for(var/datum/mind/player as anything in get_crewmember_minds())
|
||||
if(player.assigned_role?.title == target.saved_job)
|
||||
backup_players += player
|
||||
if(player.name == target.saved_identification)
|
||||
target_mind = player
|
||||
break
|
||||
if(!target_mind)
|
||||
if(!length(backup_players))
|
||||
target_mind = user.mind
|
||||
else
|
||||
target_mind = pick(backup_players)
|
||||
hidden_uplink = target.AddComponent(/datum/component/uplink, target_mind, enabled = TRUE, starting_tc = telecrystals, has_progression = TRUE)
|
||||
hidden_uplink.uplink_handler.has_objectives = TRUE
|
||||
hidden_uplink.uplink_handler.owner = target_mind
|
||||
hidden_uplink.uplink_handler.can_take_objectives = FALSE
|
||||
hidden_uplink.uplink_handler.progression_points = min(SStraitor.current_global_progression, current_progression)
|
||||
hidden_uplink.uplink_handler.generate_objectives()
|
||||
SStraitor.register_uplink_handler(hidden_uplink.uplink_handler)
|
||||
else
|
||||
hidden_uplink.add_telecrystals(telecrystals)
|
||||
telecrystals = 0
|
||||
hidden_uplink.locked = FALSE
|
||||
hidden_uplink.active = TRUE
|
||||
else
|
||||
to_chat(user, span_notice("ERROR: Could not find device."))
|
||||
|
||||
/obj/item/computer_hardware/hard_drive/role/virus/frame/attackby(obj/item/I, mob/user, params)
|
||||
. = ..()
|
||||
if(istype(I, /obj/item/stack/telecrystal))
|
||||
if(!charges)
|
||||
to_chat(user, span_notice("[src] is out of charges, it's refusing to accept [I]."))
|
||||
return
|
||||
var/obj/item/stack/telecrystal/telecrystalStack = I
|
||||
telecrystals += telecrystalStack.amount
|
||||
to_chat(user, span_notice("You slot [telecrystalStack] into [src]. The next time it's used, it will also give telecrystals."))
|
||||
telecrystalStack.use(telecrystalStack.amount)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user