mirror of
https://github.com/SPLURT-Station/S.P.L.U.R.T-Station-13.git
synced 2025-12-09 16:07:40 +00:00
1235 lines
42 KiB
Plaintext
1235 lines
42 KiB
Plaintext
//The advanced pea-green monochrome lcd of tomorrow.
|
|
|
|
GLOBAL_LIST_EMPTY(PDAs)
|
|
|
|
#define PDA_SCANNER_NONE 0
|
|
#define PDA_SCANNER_MEDICAL 1
|
|
#define PDA_SCANNER_FORENSICS 2 //unused
|
|
#define PDA_SCANNER_REAGENT 3
|
|
#define PDA_SCANNER_HALOGEN 4
|
|
#define PDA_SCANNER_GAS 5
|
|
#define PDA_SPAM_DELAY 2 MINUTES
|
|
|
|
//pda icon overlays list defines
|
|
#define PDA_OVERLAY_ALERT 1
|
|
#define PDA_OVERLAY_SCREEN 2
|
|
#define PDA_OVERLAY_ID 3
|
|
#define PDA_OVERLAY_ITEM 4
|
|
#define PDA_OVERLAY_LIGHT 5
|
|
#define PDA_OVERLAY_PAI 6
|
|
|
|
/obj/item/pda
|
|
name = "\improper PDA"
|
|
desc = "A portable microcomputer by Thinktronic Systems, LTD. Functionality determined by a preprogrammed ROM cartridge."
|
|
icon = 'icons/obj/pda_alt.dmi'
|
|
icon_state = "pda"
|
|
item_state = "electronic"
|
|
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
|
|
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
|
|
item_flags = NOBLUDGEON
|
|
w_class = WEIGHT_CLASS_TINY
|
|
slot_flags = ITEM_SLOT_ID | ITEM_SLOT_BELT
|
|
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
|
|
resistance_flags = FIRE_PROOF | ACID_PROOF
|
|
|
|
//Main variables
|
|
var/owner = null // String name of owner
|
|
var/default_cartridge = 0 // Access level defined by cartridge
|
|
var/obj/item/cartridge/cartridge = null //current cartridge
|
|
var/mode = 0 //Controls what menu the PDA will display. 0 is hub; the rest are either built in or based on cartridge.
|
|
var/list/overlays_icons = list('icons/obj/pda_alt.dmi' = list("pda-r", "screen_default", "id_overlay", "insert_overlay", "light_overlay", "pai_overlay"))
|
|
var/static/list/standard_overlays_icons = list("pda-r", "blank", "id_overlay", "insert_overlay", "light_overlay", "pai_overlay")
|
|
var/list/current_overlays //set on Initialize.
|
|
|
|
//variables exclusively used on 'update_overlays' (which should never be called directly, and 'update_icon' doesn't use args anyway)
|
|
var/new_overlays = FALSE
|
|
var/new_alert = FALSE
|
|
|
|
var/font_index = 0 //This int tells DM which font is currently selected and lets DM know when the last font has been selected so that it can cycle back to the first font when "toggle font" is pressed again.
|
|
var/font_mode = "font-family:monospace;" //The currently selected font.
|
|
var/background_color = "#808000" //The currently selected background color.
|
|
|
|
#define FONT_MONO "font-family:monospace;"
|
|
#define FONT_SHARE "font-family:\"Share Tech Mono\", monospace;letter-spacing:0px;"
|
|
#define FONT_ORBITRON "font-family:\"Orbitron\", monospace;letter-spacing:0px; font-size:15px"
|
|
#define FONT_VT "font-family:\"VT323\", monospace;letter-spacing:1px;"
|
|
#define MODE_MONO 0
|
|
#define MODE_SHARE 1
|
|
#define MODE_ORBITRON 2
|
|
#define MODE_VT 3
|
|
|
|
//Secondary variables
|
|
var/scanmode = PDA_SCANNER_NONE
|
|
var/fon = FALSE //Is the flashlight function on?
|
|
var/f_lum = 2.3 //Luminosity for the flashlight function
|
|
var/f_pow = 0.6 //Power for the flashlight function
|
|
var/f_col = "#FFCC66" //Color for the flashlight function
|
|
var/silent = FALSE //To beep or not to beep, that is the question
|
|
var/toff = FALSE //If TRUE, messenger disabled
|
|
var/tnote = null //Current Texts
|
|
var/last_text //No text spamming
|
|
var/last_everyone //No text for everyone spamming
|
|
var/last_noise //Also no honk spamming that's bad too
|
|
var/ttone = "beep" //The ringtone!
|
|
var/honkamt = 0 //How many honks left when infected with honk.exe
|
|
var/mimeamt = 0 //How many silence left when infected with mime.exe
|
|
var/note = "Congratulations, your station has chosen the Thinktronic 5230 Personal Data Assistant! To help with navigation, we have provided the following definitions. North: Fore. South: Aft. West: Port. East: Starboard. Quarter is either side of aft." //Current note in the notepad function
|
|
var/notehtml = ""
|
|
var/notescanned = FALSE // True if what is in the notekeeper was from a paper.
|
|
var/detonatable = TRUE // Can the PDA be blown up?
|
|
var/hidden = FALSE // Is the PDA hidden from the PDA list?
|
|
var/emped = FALSE
|
|
var/equipped = FALSE //used here to determine if this is the first time its been picked up
|
|
var/allow_emojis = TRUE //if the pda can send emojis and actually have them parsed as such
|
|
|
|
var/obj/item/card/id/id = null //Making it possible to slot an ID card into the PDA so it can function as both.
|
|
var/ownjob = null //related to above
|
|
|
|
var/obj/item/paicard/pai = null // A slot for a personal AI device
|
|
|
|
var/datum/picture/picture //Scanned photo
|
|
|
|
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/inserted_item //Used for pen, crayon, and lipstick insertion or removal. Same as above.
|
|
var/list/overlays_offsets // offsets to use for certain overlays
|
|
var/overlays_x_offset = 0
|
|
var/overlays_y_offset = 0
|
|
|
|
var/underline_flag = TRUE //flag for underline
|
|
|
|
var/list/blocked_pdas
|
|
|
|
/obj/item/pda/suicide_act(mob/living/carbon/user)
|
|
var/deathMessage = msg_input(user)
|
|
if (!deathMessage)
|
|
deathMessage = "i ded"
|
|
user.visible_message("<span class='suicide'>[user] is sending a message to the Grim Reaper! It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
|
tnote += "<i><b>→ To The Grim Reaper:</b></i><br>[deathMessage]<br>"//records a message in their PDA as being sent to the grim reaper
|
|
return BRUTELOSS
|
|
|
|
/obj/item/pda/examine(mob/user)
|
|
. = ..()
|
|
. += id ? "<span class='notice'>Alt-click to remove the id.</span>" : ""
|
|
if(inserted_item && (!isturf(loc)))
|
|
. += "<span class='notice'>Ctrl-click to remove [inserted_item].</span>"
|
|
if(LAZYLEN(GLOB.pda_reskins))
|
|
. += "<span class='notice'>Ctrl-shift-click it to reskin it.</span>"
|
|
|
|
/obj/item/pda/Initialize()
|
|
. = ..()
|
|
if(fon)
|
|
set_light(f_lum, f_pow, f_col)
|
|
|
|
GLOB.PDAs += src
|
|
if(default_cartridge)
|
|
cartridge = new default_cartridge(src)
|
|
if(inserted_item)
|
|
inserted_item = new inserted_item(src)
|
|
else
|
|
inserted_item = new /obj/item/pen(src)
|
|
new_overlays = TRUE
|
|
update_icon()
|
|
|
|
/obj/item/pda/CtrlShiftClick(mob/living/user)
|
|
. = ..()
|
|
if(GLOB.pda_reskins && user.canUseTopic(src, BE_CLOSE, NO_DEXTERY))
|
|
reskin_obj(user)
|
|
|
|
/obj/item/pda/reskin_obj(mob/M)
|
|
if(!LAZYLEN(GLOB.pda_reskins))
|
|
return
|
|
var/dat = "<b>Reskin options for [name]:</b>"
|
|
for(var/V in GLOB.pda_reskins)
|
|
var/output = icon2html(GLOB.pda_reskins[V], M, icon_state)
|
|
dat += "\n[V]: <span class='reallybig'>[output]</span>"
|
|
to_chat(M, dat)
|
|
|
|
var/choice = input(M, "Choose the a reskin for [src]","Reskin Object") as null|anything in GLOB.pda_reskins
|
|
var/new_icon = GLOB.pda_reskins[choice]
|
|
if(QDELETED(src) || isnull(new_icon) || new_icon == icon || !M.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
|
|
return
|
|
icon = new_icon
|
|
new_overlays = TRUE
|
|
update_icon()
|
|
to_chat(M, "[src] is now skinned as '[choice]'.")
|
|
|
|
/obj/item/pda/proc/set_new_overlays()
|
|
if(!overlays_offsets || !(icon in overlays_offsets))
|
|
overlays_x_offset = 0
|
|
overlays_y_offset = 0
|
|
else
|
|
var/list/new_offsets = overlays_offsets[icon]
|
|
if(new_offsets)
|
|
overlays_x_offset = new_offsets[1]
|
|
overlays_y_offset = new_offsets[2]
|
|
if(!(icon in overlays_icons))
|
|
current_overlays = standard_overlays_icons
|
|
return
|
|
current_overlays = overlays_icons[icon]
|
|
|
|
/obj/item/pda/equipped(mob/user, slot)
|
|
. = ..()
|
|
if(equipped || !user.client)
|
|
return
|
|
update_style(user.client)
|
|
|
|
/obj/item/pda/proc/update_style(client/C)
|
|
background_color = C.prefs.pda_color
|
|
switch(C.prefs.pda_style)
|
|
if(MONO)
|
|
font_index = MODE_MONO
|
|
font_mode = FONT_MONO
|
|
if(SHARE)
|
|
font_index = MODE_SHARE
|
|
font_mode = FONT_SHARE
|
|
if(ORBITRON)
|
|
font_index = MODE_ORBITRON
|
|
font_mode = FONT_ORBITRON
|
|
if(VT)
|
|
font_index = MODE_VT
|
|
font_mode = FONT_VT
|
|
else
|
|
font_index = MODE_MONO
|
|
font_mode = FONT_MONO
|
|
var/pref_skin = GLOB.pda_reskins[C.prefs.pda_skin]
|
|
if(icon != pref_skin)
|
|
icon = pref_skin
|
|
new_overlays = TRUE
|
|
update_icon()
|
|
equipped = TRUE
|
|
|
|
/obj/item/pda/proc/update_label()
|
|
name = "PDA-[owner] ([ownjob])" //Name generalisation
|
|
|
|
/obj/item/pda/GetAccess()
|
|
if(id)
|
|
return id.GetAccess()
|
|
else
|
|
return ..()
|
|
|
|
/obj/item/pda/GetID()
|
|
return id
|
|
|
|
/obj/item/pda/RemoveID()
|
|
return do_remove_id()
|
|
|
|
/obj/item/pda/InsertID(obj/item/inserting_item)
|
|
var/obj/item/card/inserting_id = inserting_item.RemoveID()
|
|
if(!inserting_id)
|
|
return
|
|
insert_id(inserting_id)
|
|
if(id == inserting_id)
|
|
return TRUE
|
|
return FALSE
|
|
|
|
/obj/item/pda/update_overlays()
|
|
. = ..()
|
|
if(new_overlays)
|
|
set_new_overlays()
|
|
var/screen_state = new_alert ? current_overlays[PDA_OVERLAY_ALERT] : current_overlays[PDA_OVERLAY_SCREEN]
|
|
var/mutable_appearance/overlay = mutable_appearance(icon, screen_state)
|
|
overlay.pixel_x = overlays_x_offset
|
|
overlay.pixel_y = overlays_y_offset
|
|
. += new /mutable_appearance(overlay)
|
|
if(id)
|
|
overlay.icon_state = current_overlays[PDA_OVERLAY_ID]
|
|
. += new /mutable_appearance(overlay)
|
|
if(inserted_item)
|
|
overlay.icon_state = current_overlays[PDA_OVERLAY_ITEM]
|
|
. += new /mutable_appearance(overlay)
|
|
if(fon)
|
|
overlay.icon_state = current_overlays[PDA_OVERLAY_LIGHT]
|
|
. += new /mutable_appearance(overlay)
|
|
if(pai)
|
|
overlay.icon_state = "[current_overlays[PDA_OVERLAY_PAI]][pai.pai ? "" : "_off"]"
|
|
. += overlay
|
|
new_overlays = FALSE
|
|
new_alert = FALSE
|
|
|
|
/obj/item/pda/MouseDrop(mob/over, src_location, over_location)
|
|
var/mob/M = usr
|
|
if((M == over) && usr.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
|
|
return attack_self(M)
|
|
return ..()
|
|
|
|
/obj/item/pda/attack_self_tk(mob/user)
|
|
to_chat(user, "<span class='warning'>The PDA's capacitive touch screen doesn't seem to respond!</span>")
|
|
return
|
|
|
|
/obj/item/pda/interact(mob/user)
|
|
if(!user.IsAdvancedToolUser())
|
|
to_chat(user, "<span class='warning'>You don't have the dexterity to do this!</span>")
|
|
return
|
|
|
|
..()
|
|
|
|
var/datum/asset/spritesheet/assets = get_asset_datum(/datum/asset/spritesheet/simple/pda)
|
|
assets.send(user)
|
|
|
|
var/datum/asset/spritesheet/emoji_s = get_asset_datum(/datum/asset/spritesheet/chat)
|
|
emoji_s.send(user) //Already sent by chat but no harm doing this
|
|
|
|
user.set_machine(src)
|
|
|
|
var/dat = "<!DOCTYPE html><html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8'><title>Personal Data Assistant</title><link href=\"https://fonts.googleapis.com/css?family=Orbitron|Share+Tech+Mono|VT323\" rel=\"stylesheet\"></head><body bgcolor=\"" + background_color + "\"><style>body{" + font_mode + "}ul,ol{list-style-type: none;}a, a:link, a:visited, a:active, a:hover { color: #000000;text-decoration:none; }img {border-style:none;}a img{padding-right: 9px;}</style>"
|
|
dat += assets.css_tag()
|
|
dat += emoji_s.css_tag()
|
|
|
|
dat += "<a href='byond://?src=[REF(src)];choice=Refresh'>[PDAIMG(refresh)]Refresh</a>"
|
|
|
|
if ((!isnull(cartridge)) && (mode == 0))
|
|
dat += " | <a href='byond://?src=[REF(src)];choice=Eject'>[PDAIMG(eject)]Eject [cartridge]</a>"
|
|
if (mode)
|
|
dat += " | <a href='byond://?src=[REF(src)];choice=Return'>[PDAIMG(menu)]Return</a>"
|
|
|
|
if (mode == 0)
|
|
dat += "<div align=\"center\">"
|
|
dat += "<br><a href='byond://?src=[REF(src)];choice=Toggle_Font'>Toggle Font</a>"
|
|
dat += " | <a href='byond://?src=[REF(src)];choice=Change_Color'>Change Color</a>"
|
|
dat += " | <a href='byond://?src=[REF(src)];choice=Toggle_Underline'>Toggle Underline</a>" //underline button
|
|
|
|
dat += "</div>"
|
|
|
|
dat += "<br>"
|
|
|
|
if (!owner)
|
|
dat += "Warning: No owner information entered. Please swipe card.<br><br>"
|
|
dat += "<a href='byond://?src=[REF(src)];choice=Refresh'>[PDAIMG(refresh)]Retry</a>"
|
|
else
|
|
switch (mode)
|
|
if (0)
|
|
dat += "<h2>PERSONAL DATA ASSISTANT v.1.2</h2>"
|
|
dat += "Owner: [owner], [ownjob]<br>"
|
|
dat += text("ID: <a href='?src=[REF(src)];choice=Authenticate'>[id ? "[id.registered_name], [id.assignment]" : "----------"]")
|
|
dat += text("<br><a href='?src=[REF(src)];choice=UpdateInfo'>[id ? "Update PDA Info" : ""]</A><br><br>")
|
|
|
|
dat += "[STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)]<br>" //:[world.time / 100 % 6][world.time / 100 % 10]"
|
|
dat += "[time2text(world.realtime, "MMM DD")] [GLOB.year_integer]"
|
|
|
|
dat += "<br><br>"
|
|
|
|
dat += "<h4>General Functions</h4>"
|
|
dat += "<ul>"
|
|
dat += "<li><a href='byond://?src=[REF(src)];choice=1'>[PDAIMG(notes)]Notekeeper</a></li>"
|
|
dat += "<li><a href='byond://?src=[REF(src)];choice=2'>[PDAIMG(mail)]Messenger</a></li>"
|
|
|
|
if (cartridge)
|
|
if (cartridge.access & CART_CLOWN)
|
|
dat += "<li><a href='byond://?src=[REF(src)];choice=Honk'>[PDAIMG(honk)]Honk Synthesizer</a></li>"
|
|
dat += "<li><a href='byond://?src=[REF(src)];choice=Trombone'>[PDAIMG(honk)]Sad Trombone</a></li>"
|
|
if (cartridge.access & CART_MANIFEST)
|
|
dat += "<li><a href='byond://?src=[REF(src)];choice=41'>[PDAIMG(notes)]View Crew Manifest</a></li>"
|
|
if(cartridge.access & CART_STATUS_DISPLAY)
|
|
dat += "<li><a href='byond://?src=[REF(src)];choice=42'>[PDAIMG(status)]Set Status Display</a></li>"
|
|
dat += "</ul>"
|
|
if (cartridge.access & CART_ENGINE)
|
|
dat += "<h4>Engineering Functions</h4>"
|
|
dat += "<ul>"
|
|
dat += "<li><a href='byond://?src=[REF(src)];choice=43'>[PDAIMG(power)]Power Monitor</a></li>"
|
|
dat += "</ul>"
|
|
if (cartridge.access & CART_MEDICAL)
|
|
dat += "<h4>Medical Functions</h4>"
|
|
dat += "<ul>"
|
|
dat += "<li><a href='byond://?src=[REF(src)];choice=44'>[PDAIMG(medical)]Medical Records</a></li>"
|
|
dat += "<li><a href='byond://?src=[REF(src)];choice=Medical Scan'>[PDAIMG(scanner)][scanmode == 1 ? "Disable" : "Enable"] Medical Scanner</a></li>"
|
|
dat += "</ul>"
|
|
if (cartridge.access & CART_SECURITY)
|
|
dat += "<h4>Security Functions</h4>"
|
|
dat += "<ul>"
|
|
dat += "<li><a href='byond://?src=[REF(src)];choice=45'>[PDAIMG(cuffs)]Security Records</A></li>"
|
|
dat += "</ul>"
|
|
if(cartridge.access & CART_QUARTERMASTER)
|
|
dat += "<h4>Quartermaster Functions:</h4>"
|
|
dat += "<ul>"
|
|
dat += "<li><a href='byond://?src=[REF(src)];choice=47'>[PDAIMG(crate)]Supply Records</A></li>"
|
|
dat += "<li><a href='byond://?src=[REF(src)];choice=48'>[PDAIMG(crate)]Ore Silo Logs</a></li>"
|
|
dat += "</ul>"
|
|
dat += "</ul>"
|
|
|
|
dat += "<h4>Utilities</h4>"
|
|
dat += "<ul>"
|
|
if (cartridge)
|
|
if(cartridge.bot_access_flags)
|
|
dat += "<li><a href='byond://?src=[REF(src)];choice=54'>[PDAIMG(medbot)]Bots Access</a></li>"
|
|
if (cartridge.access & CART_JANITOR)
|
|
dat += "<li><a href='byond://?src=[REF(src)];choice=49'>[PDAIMG(bucket)]Custodial Locator</a></li>"
|
|
if(cartridge.access & CART_MIME)
|
|
dat += "<li><a href='byond://?src=[REF(src)];choice=55'>[PDAIMG(emoji)]Emoji Guidebook</a></li>"
|
|
if (istype(cartridge.radio))
|
|
dat += "<li><a href='byond://?src=[REF(src)];choice=40'>[PDAIMG(signaler)]Signaler System</a></li>"
|
|
if (cartridge.access & CART_NEWSCASTER)
|
|
dat += "<li><a href='byond://?src=[REF(src)];choice=53'>[PDAIMG(notes)]Newscaster Access </a></li>"
|
|
if (cartridge.access & CART_REAGENT_SCANNER)
|
|
dat += "<li><a href='byond://?src=[REF(src)];choice=Reagent Scan'>[PDAIMG(reagent)][scanmode == 3 ? "Disable" : "Enable"] Reagent Scanner</a></li>"
|
|
if (cartridge.access & CART_ENGINE)
|
|
dat += "<li><a href='byond://?src=[REF(src)];choice=Halogen Counter'>[PDAIMG(reagent)][scanmode == 4 ? "Disable" : "Enable"] Halogen Counter</a></li>"
|
|
if (cartridge.access & CART_ATMOS)
|
|
dat += "<li><a href='byond://?src=[REF(src)];choice=Gas Scan'>[PDAIMG(reagent)][scanmode == 5 ? "Disable" : "Enable"] Gas Scanner</a></li>"
|
|
if (cartridge.access & CART_REMOTE_DOOR)
|
|
dat += "<li><a href='byond://?src=[REF(src)];choice=Toggle Door'>[PDAIMG(rdoor)]Toggle Remote Door</a></li>"
|
|
if (cartridge.access & CART_DRONEPHONE)
|
|
dat += "<li><a href='byond://?src=[REF(src)];choice=Drone Phone'>[PDAIMG(dronephone)]Drone Phone</a></li>"
|
|
dat += "<li><a href='byond://?src=[REF(src)];choice=3'>[PDAIMG(atmos)]Atmospheric Scan</a></li>"
|
|
dat += "<li><a href='byond://?src=[REF(src)];choice=Light'>[PDAIMG(flashlight)][fon ? "Disable" : "Enable"] Flashlight</a></li>"
|
|
if (pai)
|
|
if(pai.loc != src)
|
|
pai = null
|
|
update_icon()
|
|
else
|
|
dat += "<li><a href='byond://?src=[REF(src)];choice=pai;option=1'>pAI Device Configuration</a></li>"
|
|
dat += "<li><a href='byond://?src=[REF(src)];choice=pai;option=2'>Eject pAI Device</a></li>"
|
|
dat += "</ul>"
|
|
|
|
if (1)
|
|
dat += "<h4>[PDAIMG(notes)] Notekeeper V2.2</h4>"
|
|
dat += "<a href='byond://?src=[REF(src)];choice=Edit'>Edit</a><br>"
|
|
if(notescanned)
|
|
dat += "(This is a scanned image, editing it may cause some text formatting to change.)<br>"
|
|
dat += "<HR><font face=\"[PEN_FONT]\">[(!notehtml ? note : notehtml)]</font>"
|
|
|
|
if (2)
|
|
dat += "<h4>[PDAIMG(mail)] SpaceMessenger V3.9.6</h4>"
|
|
dat += "<a href='byond://?src=[REF(src)];choice=Toggle Ringer'>[PDAIMG(bell)]Ringer: [silent == 1 ? "Off" : "On"]</a> | "
|
|
dat += "<a href='byond://?src=[REF(src)];choice=Toggle Messenger'>[PDAIMG(mail)]Send / Receive: [toff == 1 ? "Off" : "On"]</a> | "
|
|
dat += "<a href='byond://?src=[REF(src)];choice=Ringtone'>[PDAIMG(bell)]Set Ringtone</a> | "
|
|
dat += "<a href='byond://?src=[REF(src)];choice=21'>[PDAIMG(mail)]Messages</a><br>"
|
|
|
|
if(cartridge)
|
|
dat += cartridge.message_header()
|
|
|
|
dat += "<h4>[PDAIMG(menu)] Detected PDAs</h4>"
|
|
|
|
dat += "<ul>"
|
|
var/count = 0
|
|
|
|
if (!toff)
|
|
for (var/obj/item/pda/P in sortNames(get_viewable_pdas()))
|
|
if (P == src)
|
|
continue
|
|
if(P.owner in blocked_pdas)
|
|
dat += "<li><a href='byond://?src=[REF(src)];choice=unblock_pda;target=[P.owner]'>(BLOCKED - CLICK TO UNBLOCK) [P]</a>"
|
|
else
|
|
dat += "<li><a href='byond://?src=[REF(src)];choice=Message;target=[REF(P)]'>[P]</a>"
|
|
if(cartridge)
|
|
dat += cartridge.message_special(P)
|
|
dat += "</li>"
|
|
count++
|
|
dat += "</ul>"
|
|
if (count == 0)
|
|
dat += "None detected.<br>"
|
|
else if(cartridge && cartridge.spam_enabled)
|
|
dat += "<a href='byond://?src=[REF(src)];choice=MessageAll'>Send To All</a>"
|
|
|
|
if(21)
|
|
dat += "<h4>[PDAIMG(mail)] SpaceMessenger V3.9.6</h4>"
|
|
dat += "<a href='byond://?src=[REF(src)];choice=Clear'>[PDAIMG(blank)]Clear Messages</a>"
|
|
|
|
dat += "<h4>[PDAIMG(mail)] Messages</h4>"
|
|
|
|
dat += tnote
|
|
dat += "<br>"
|
|
|
|
if (3)
|
|
dat += "<h4>[PDAIMG(atmos)] Atmospheric Readings</h4>"
|
|
|
|
var/turf/T = user.loc
|
|
if (isnull(T))
|
|
dat += "Unable to obtain a reading.<br>"
|
|
else
|
|
var/datum/gas_mixture/environment = T.return_air()
|
|
|
|
var/pressure = environment.return_pressure()
|
|
var/total_moles = environment.total_moles()
|
|
|
|
dat += "Air Pressure: [round(pressure,0.1)] kPa<br>"
|
|
|
|
if (total_moles)
|
|
for(var/id in environment.get_gases())
|
|
var/gas_level = environment.get_moles(id)/total_moles
|
|
if(gas_level > 0)
|
|
dat += "[GLOB.meta_gas_names[id]]: [round(gas_level*100, 0.01)]%<br>"
|
|
|
|
dat += "Temperature: [round(environment.return_temperature()-T0C)]°C<br>"
|
|
dat += "<br>"
|
|
else//Else it links to the cart menu proc. Although, it really uses menu hub 4--menu 4 doesn't really exist as it simply redirects to hub.
|
|
dat += cartridge.generate_menu()
|
|
|
|
dat += "</body></html>"
|
|
|
|
if (underline_flag)
|
|
dat = replacetext(dat, "text-decoration:none", "text-decoration:underline")
|
|
if (!underline_flag)
|
|
dat = replacetext(dat, "text-decoration:underline", "text-decoration:none")
|
|
|
|
user << browse(dat, "window=pda;size=400x450;border=1;can_resize=1;can_minimize=0")
|
|
onclose(user, "pda", src)
|
|
|
|
/obj/item/pda/Topic(href, href_list)
|
|
..()
|
|
var/mob/living/U = usr
|
|
//Looking for master was kind of pointless since PDAs don't appear to have one.
|
|
|
|
if(usr.canUseTopic(src, BE_CLOSE, FALSE, NO_TK, FALSE) && !href_list["close"])
|
|
add_fingerprint(U)
|
|
U.set_machine(src)
|
|
|
|
switch(href_list["choice"])
|
|
|
|
//BASIC FUNCTIONS===================================
|
|
|
|
if("Refresh")//Refresh, goes to the end of the proc.
|
|
if (!silent)
|
|
playsound(src, 'sound/machines/terminal_select.ogg', 15, 1)
|
|
|
|
if ("Toggle_Font")
|
|
//CODE REVISION 2
|
|
font_index = (font_index + 1) % 4
|
|
|
|
switch(font_index)
|
|
if (MODE_MONO)
|
|
font_mode = FONT_MONO
|
|
if (MODE_SHARE)
|
|
font_mode = FONT_SHARE
|
|
if (MODE_ORBITRON)
|
|
font_mode = FONT_ORBITRON
|
|
if (MODE_VT)
|
|
font_mode = FONT_VT
|
|
if (!silent)
|
|
playsound(src, 'sound/machines/terminal_select.ogg', 15, 1)
|
|
|
|
if ("Change_Color")
|
|
var/new_color = input("Please enter a color name or hex value (Default is \'#808000\').",background_color)as color
|
|
background_color = new_color
|
|
if (!silent)
|
|
playsound(src, 'sound/machines/terminal_select.ogg', 15, 1)
|
|
|
|
if ("Toggle_Underline")
|
|
underline_flag = !underline_flag
|
|
if (!silent)
|
|
playsound(src, 'sound/machines/terminal_select.ogg', 15, 1)
|
|
|
|
if("Return")//Return
|
|
if(mode<=9)
|
|
mode = 0
|
|
else
|
|
mode = round(mode/10)
|
|
if(mode==4 || mode == 5)//Fix for cartridges. Redirects to hub.
|
|
mode = 0
|
|
if (!silent)
|
|
playsound(src, 'sound/machines/terminal_select.ogg', 15, 1)
|
|
|
|
if ("Authenticate")//Checks for ID
|
|
id_check(U)
|
|
|
|
if("UpdateInfo")
|
|
ownjob = id.assignment
|
|
if(istype(id, /obj/item/card/id/syndicate))
|
|
owner = id.registered_name
|
|
update_label()
|
|
if (!silent)
|
|
playsound(src, 'sound/machines/terminal_processing.ogg', 15, 1)
|
|
addtimer(CALLBACK(GLOBAL_PROC, .proc/playsound, src, 'sound/machines/terminal_success.ogg', 15, 1), 13)
|
|
|
|
if("Eject")//Ejects the cart, only done from hub.
|
|
if (!isnull(cartridge))
|
|
U.put_in_hands(cartridge)
|
|
to_chat(U, "<span class='notice'>You remove [cartridge] from [src].</span>")
|
|
scanmode = PDA_SCANNER_NONE
|
|
cartridge.host_pda = null
|
|
cartridge = null
|
|
update_icon()
|
|
if (!silent)
|
|
playsound(src, 'sound/machines/terminal_eject_disc.ogg', 50, 1)
|
|
|
|
//MENU FUNCTIONS===================================
|
|
|
|
if("0")//Hub
|
|
mode = 0
|
|
if (!silent)
|
|
playsound(src, 'sound/machines/terminal_select.ogg', 15, 1)
|
|
if("1")//Notes
|
|
mode = 1
|
|
if (!silent)
|
|
playsound(src, 'sound/machines/terminal_select.ogg', 15, 1)
|
|
if("2")//Messenger
|
|
mode = 2
|
|
if (!silent)
|
|
playsound(src, 'sound/machines/terminal_select.ogg', 15, 1)
|
|
if("21")//Read messeges
|
|
mode = 21
|
|
if (!silent)
|
|
playsound(src, 'sound/machines/terminal_select.ogg', 15, 1)
|
|
if("3")//Atmos scan
|
|
mode = 3
|
|
if (!silent)
|
|
playsound(src, 'sound/machines/terminal_select.ogg', 15, 1)
|
|
if("4")//Redirects to hub
|
|
mode = 0
|
|
if (!silent)
|
|
playsound(src, 'sound/machines/terminal_select.ogg', 15, 1)
|
|
|
|
|
|
//MAIN FUNCTIONS===================================
|
|
|
|
if("Light")
|
|
toggle_light()
|
|
if (!silent)
|
|
playsound(src, 'sound/machines/terminal_select.ogg', 15, 1)
|
|
|
|
if("Medical Scan")
|
|
if(scanmode == PDA_SCANNER_MEDICAL)
|
|
scanmode = PDA_SCANNER_NONE
|
|
else if((!isnull(cartridge)) && (cartridge.access & CART_MEDICAL))
|
|
scanmode = PDA_SCANNER_MEDICAL
|
|
if (!silent)
|
|
playsound(src, 'sound/machines/terminal_select.ogg', 15, 1)
|
|
|
|
if("Reagent Scan")
|
|
if(scanmode == PDA_SCANNER_REAGENT)
|
|
scanmode = PDA_SCANNER_NONE
|
|
else if((!isnull(cartridge)) && (cartridge.access & CART_REAGENT_SCANNER))
|
|
scanmode = PDA_SCANNER_REAGENT
|
|
if (!silent)
|
|
playsound(src, 'sound/machines/terminal_select.ogg', 15, 1)
|
|
|
|
if("Halogen Counter")
|
|
if(scanmode == PDA_SCANNER_HALOGEN)
|
|
scanmode = PDA_SCANNER_NONE
|
|
else if((!isnull(cartridge)) && (cartridge.access & CART_ENGINE))
|
|
scanmode = PDA_SCANNER_HALOGEN
|
|
if (!silent)
|
|
playsound(src, 'sound/machines/terminal_select.ogg', 15, 1)
|
|
|
|
if("Honk")
|
|
if ( !(last_noise && world.time < last_noise + 20) )
|
|
playsound(src, 'sound/items/bikehorn.ogg', 50, 1)
|
|
last_noise = world.time
|
|
|
|
if("Trombone")
|
|
if ( !(last_noise && world.time < last_noise + 20) )
|
|
playsound(src, 'sound/misc/sadtrombone.ogg', 50, 1)
|
|
last_noise = world.time
|
|
|
|
if("Gas Scan")
|
|
if(scanmode == PDA_SCANNER_GAS)
|
|
scanmode = PDA_SCANNER_NONE
|
|
else if((!isnull(cartridge)) && (cartridge.access & CART_ATMOS))
|
|
scanmode = PDA_SCANNER_GAS
|
|
if (!silent)
|
|
playsound(src, 'sound/machines/terminal_select.ogg', 15, 1)
|
|
|
|
if("Drone Phone")
|
|
var/alert_s = input(U,"Alert severity level","Ping Drones",null) as null|anything in list("Low","Medium","High","Critical")
|
|
var/area/A = get_area(U)
|
|
if(A && alert_s && !QDELETED(U))
|
|
var/msg = "<span class='boldnotice'>NON-DRONE PING: [U.name]: [alert_s] priority alert in [A.name]!</span>"
|
|
_alert_drones(msg, TRUE, U)
|
|
to_chat(U, msg)
|
|
if (!silent)
|
|
playsound(src, 'sound/machines/terminal_success.ogg', 15, 1)
|
|
|
|
|
|
//NOTEKEEPER FUNCTIONS===================================
|
|
|
|
if ("Edit")
|
|
var/n = stripped_multiline_input(U, "Please enter message", name, note)
|
|
if (in_range(src, U) && loc == U)
|
|
if (mode == 1 && n)
|
|
note = n
|
|
notehtml = parsemarkdown(n, U)
|
|
notescanned = FALSE
|
|
else
|
|
U << browse(null, "window=pda")
|
|
return
|
|
|
|
//MESSENGER FUNCTIONS===================================
|
|
|
|
if("Toggle Messenger")
|
|
toff = !toff
|
|
if("Toggle Ringer")//If viewing texts then erase them, if not then toggle silent status
|
|
silent = !silent
|
|
if("Clear")//Clears messages
|
|
tnote = null
|
|
if("Ringtone")
|
|
var/t = stripped_input(U, "Please enter new ringtone", name, ttone, 20)
|
|
if(in_range(src, U) && loc == U && t)
|
|
if(SEND_SIGNAL(src, COMSIG_PDA_CHANGE_RINGTONE, U, t) & COMPONENT_STOP_RINGTONE_CHANGE)
|
|
U << browse(null, "window=pda")
|
|
return
|
|
else
|
|
ttone = t
|
|
else
|
|
U << browse(null, "window=pda")
|
|
return
|
|
if("Message")
|
|
create_message(U, locate(href_list["target"]))
|
|
|
|
if("MessageAll")
|
|
if(cartridge?.spam_enabled)
|
|
send_to_all(U)
|
|
|
|
if("toggle_block")
|
|
toggle_blocking(usr, href_list["target"])
|
|
|
|
if("block_pda")
|
|
block_pda(usr, href_list["target"])
|
|
|
|
if("unblock_pda")
|
|
unblock_pda(usr, href_list["target"])
|
|
|
|
if("cart")
|
|
if(cartridge)
|
|
cartridge.special(U, href_list)
|
|
else
|
|
U << browse(null, "window=pda")
|
|
return
|
|
|
|
//SYNDICATE FUNCTIONS===================================
|
|
|
|
if("Toggle Door")
|
|
if(cartridge && cartridge.access & CART_REMOTE_DOOR)
|
|
for(var/obj/machinery/door/poddoor/M in GLOB.machines)
|
|
if(M.id == cartridge.remote_door_id)
|
|
if(M.density)
|
|
M.open()
|
|
else
|
|
M.close()
|
|
|
|
//pAI FUNCTIONS===================================
|
|
if("pai")
|
|
switch(href_list["option"])
|
|
if("1") // Configure pAI device
|
|
pai.attack_self(U)
|
|
if("2") // Eject pAI device
|
|
var/turf/T = get_turf(loc)
|
|
if(T)
|
|
pai.forceMove(T)
|
|
|
|
//LINK FUNCTIONS===================================
|
|
|
|
else//Cartridge menu linking
|
|
mode = max(text2num(href_list["choice"]), 0)
|
|
|
|
else//If not in range, can't interact or not using the pda.
|
|
U.unset_machine()
|
|
U << browse(null, "window=pda")
|
|
return
|
|
|
|
//EXTRA FUNCTIONS===================================
|
|
|
|
if (mode == 2 || mode == 21)//To clear message overlays.
|
|
update_icon()
|
|
|
|
if ((honkamt > 0) && (prob(60)))//For clown virus.
|
|
honkamt--
|
|
playsound(src, 'sound/items/bikehorn.ogg', 30, 1)
|
|
|
|
if(U.machine == src && href_list["skiprefresh"]!="1")//Final safety.
|
|
attack_self(U)//It auto-closes the menu prior if the user is not in range and so on.
|
|
else
|
|
U.unset_machine()
|
|
U << browse(null, "window=pda")
|
|
return
|
|
|
|
/obj/item/pda/proc/remove_id(mob/user)
|
|
if(hasSiliconAccessInArea(user) || !user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
|
|
return
|
|
do_remove_id(user)
|
|
|
|
/obj/item/pda/proc/do_remove_id(mob/user)
|
|
if(!id)
|
|
return
|
|
if(user)
|
|
user.put_in_hands(id)
|
|
to_chat(user, "<span class='notice'>You remove the ID from the [name].</span>")
|
|
else
|
|
id.forceMove(get_turf(src))
|
|
|
|
. = id
|
|
id = null
|
|
update_icon()
|
|
|
|
if(ishuman(loc))
|
|
var/mob/living/carbon/human/H = loc
|
|
if(H.wear_id == src)
|
|
H.sec_hud_set_ID()
|
|
|
|
/obj/item/pda/proc/msg_input(mob/living/U = usr)
|
|
var/t = stripped_input(U, "Please enter message", name)
|
|
if (!t || toff)
|
|
return
|
|
if(!U.canUseTopic(src, BE_CLOSE, FALSE, NO_TK, FALSE))
|
|
return
|
|
if(emped)
|
|
t = Gibberish(t, 100)
|
|
return t
|
|
|
|
/obj/item/pda/proc/send_message(mob/living/user, list/obj/item/pda/targets, everyone)
|
|
var/message = msg_input(user)
|
|
if(!message || !targets.len)
|
|
return
|
|
if((last_text && world.time < last_text + 10) || (everyone && last_everyone && world.time < last_everyone + PDA_SPAM_DELAY))
|
|
return
|
|
if(prob(1))
|
|
message += "\nSent from my PDA"
|
|
// Send the signal
|
|
var/list/string_targets = list()
|
|
var/list/string_blocked
|
|
for(var/obj/item/pda/P in targets)
|
|
if(owner in P.blocked_pdas)
|
|
LAZYADD(string_blocked, P.owner)
|
|
continue
|
|
if(P.owner && P.ownjob) // != src is checked by the UI
|
|
string_targets += "[P.owner] ([P.ownjob])"
|
|
if(string_blocked)
|
|
string_blocked = english_list(string_blocked)
|
|
to_chat(user, "<span class='warning'>[icon2html(src, user)] The following recipients have blocked your message: [string_blocked].</span>")
|
|
for (var/obj/machinery/computer/message_monitor/M in targets)
|
|
// In case of "Reply" to a message from a console, this will make the
|
|
// message be logged successfully. If the console is impersonating
|
|
// someone by matching their name and job, the reply will reach the
|
|
// impersonated PDA.
|
|
string_targets += "[M.customsender] ([M.customjob])"
|
|
if (!string_targets.len)
|
|
return
|
|
|
|
var/datum/signal/subspace/pda/signal = new(src, list(
|
|
"name" = "[owner]",
|
|
"job" = "[ownjob]",
|
|
"message" = message,
|
|
"targets" = string_targets,
|
|
"emojis" = allow_emojis
|
|
))
|
|
if (picture)
|
|
signal.data["photo"] = picture
|
|
signal.send_to_receivers()
|
|
|
|
// If it didn't reach, note that fact
|
|
if (!signal.data["done"])
|
|
to_chat(user, "<span class='notice'>ERROR: Server isn't responding.</span>")
|
|
if (!silent)
|
|
playsound(src, 'sound/machines/terminal_error.ogg', 15, 1)
|
|
return
|
|
|
|
var/target_text = signal.format_target()
|
|
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
|
|
tnote += "<i><b>→ To [target_text]:</b></i><br>[signal.format_message()]<br>"
|
|
// Show it to ghosts
|
|
var/ghost_message = "<span class='name'>[owner] </span><span class='game say'>PDA Message</span> --> <span class='name'>[target_text]</span>: <span class='message'>[signal.format_message()]</span>"
|
|
for(var/i in GLOB.dead_mob_list)
|
|
var/mob/M = i
|
|
if(M?.client && M.client.prefs.chat_toggles & CHAT_GHOSTPDA)
|
|
to_chat(M, "[FOLLOW_LINK(M, user)] [ghost_message]")
|
|
to_chat(user, "<span class='info'>Message sent to [target_text]: \"[message]\"</span>")
|
|
// Log in the talk log
|
|
user.log_talk(message, LOG_PDA, tag="PDA: [initial(name)] to [target_text] (BLOCKED:[string_blocked])")
|
|
if (!silent)
|
|
playsound(src, 'sound/machines/terminal_success.ogg', 15, 1)
|
|
// Reset the photo
|
|
picture = null
|
|
last_text = world.time
|
|
if (everyone)
|
|
last_everyone = world.time
|
|
|
|
/obj/item/pda/proc/receive_message(datum/signal/subspace/pda/signal)
|
|
tnote += "<i><b>← From <a href='byond://?src=[REF(src)];choice=Message;target=[REF(signal.source)]'>[signal.data["name"]]</a> ([signal.data["job"]]):</b></i> <a href='byond://?src=[REF(src)];choice=toggle_block;target=[signal.data["name"]]'>(BLOCK/UNBLOCK)</a><br>[signal.format_message()]<br>"
|
|
if (!silent)
|
|
playsound(src, 'sound/machines/twobeep.ogg', 50, 1)
|
|
audible_message("[icon2html(src, hearers(src))] *[ttone]*", null, 3)
|
|
//Search for holder of the PDA.
|
|
var/mob/living/L = null
|
|
if(loc && isliving(loc))
|
|
L = loc
|
|
//Maybe they are a pAI!
|
|
else
|
|
L = get(src, /mob/living/silicon)
|
|
|
|
if(L && L.stat != UNCONSCIOUS)
|
|
var/hrefstart
|
|
var/hrefend
|
|
if (isAI(L))
|
|
hrefstart = "<a href='?src=[REF(L)];track=[html_encode(signal.data["name"])]'>"
|
|
hrefend = "</a>"
|
|
|
|
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)
|
|
|
|
to_chat(L, "[icon2html(src)] <b>Message from [hrefstart][signal.data["name"]] ([signal.data["job"]])[hrefend], </b>[inbound_message] (<a href='byond://?src=[REF(src)];choice=Message;skiprefresh=1;target=[REF(signal.source)]'>Reply</a>) (<a href='byond://?src=[REF(src)];choice=toggle_block;target=[signal.data["name"]]'>BLOCK/UNBLOCK</a>)")
|
|
|
|
new_alert = TRUE
|
|
update_icon(TRUE)
|
|
|
|
/obj/item/pda/proc/send_to_all(mob/living/U)
|
|
if (last_everyone && world.time < last_everyone + PDA_SPAM_DELAY)
|
|
to_chat(U,"<span class='warning'>Send To All function is still on cooldown.")
|
|
return
|
|
send_message(U,get_viewable_pdas(), TRUE)
|
|
|
|
/obj/item/pda/proc/create_message(mob/living/U, obj/item/pda/P)
|
|
send_message(U,list(P))
|
|
|
|
/obj/item/pda/proc/toggle_blocking(mob/user, target)
|
|
if(target in blocked_pdas)
|
|
unblock_pda(user, target)
|
|
else
|
|
block_pda(user, target)
|
|
|
|
/obj/item/pda/proc/block_pda(mob/user, target)
|
|
to_chat(user, "<span class='notice'>[icon2html(src, user)] [target] blocked from messages. Use the messenger PDA list to unblock.</span>")
|
|
LAZYOR(blocked_pdas, target)
|
|
|
|
/obj/item/pda/proc/unblock_pda(mob/user, target)
|
|
to_chat(user, "<span class='notice'>[icon2html(src, user)] [target] unblocked from messages.</span>")
|
|
LAZYREMOVE(blocked_pdas, target)
|
|
|
|
/obj/item/pda/AltClick(mob/user)
|
|
. = ..()
|
|
if(id)
|
|
remove_id(user)
|
|
playsound(src, 'sound/machines/terminal_eject_disc.ogg', 50, 1)
|
|
else
|
|
remove_pen(user)
|
|
playsound(src, 'sound/machines/button4.ogg', 50, 1)
|
|
return TRUE
|
|
|
|
/obj/item/pda/CtrlClick(mob/user)
|
|
..()
|
|
|
|
if(isturf(loc)) //stops the user from dragging the PDA by ctrl-clicking it.
|
|
return
|
|
|
|
remove_pen(user)
|
|
|
|
/obj/item/pda/verb/verb_toggle_light()
|
|
set category = "Object"
|
|
set name = "Toggle Flashlight"
|
|
|
|
toggle_light()
|
|
|
|
/obj/item/pda/verb/verb_remove_id()
|
|
set category = "Object"
|
|
set name = "Eject ID"
|
|
set src in usr
|
|
|
|
if(id)
|
|
remove_id(usr)
|
|
else
|
|
to_chat(usr, "<span class='warning'>This PDA does not have an ID in it!</span>")
|
|
|
|
/obj/item/pda/verb/verb_remove_pen()
|
|
set category = "Object"
|
|
set name = "Remove Pen"
|
|
set src in usr
|
|
|
|
remove_pen()
|
|
|
|
/obj/item/pda/proc/toggle_light()
|
|
if(hasSiliconAccessInArea(usr) || !usr.canUseTopic(src, BE_CLOSE))
|
|
return
|
|
if(fon)
|
|
fon = FALSE
|
|
set_light(0)
|
|
else if(f_lum)
|
|
fon = TRUE
|
|
set_light(f_lum, f_pow, f_col)
|
|
update_icon()
|
|
|
|
/obj/item/pda/proc/remove_pen()
|
|
|
|
if(hasSiliconAccessInArea(usr) || !usr.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
|
|
return
|
|
|
|
if(inserted_item)
|
|
usr.put_in_hands(inserted_item)
|
|
to_chat(usr, "<span class='notice'>You remove [inserted_item] from [src].</span>")
|
|
inserted_item = null
|
|
update_icon()
|
|
else
|
|
to_chat(usr, "<span class='warning'>This PDA does not have a pen in it!</span>")
|
|
|
|
//trying to insert or remove an id
|
|
/obj/item/pda/proc/id_check(mob/user, obj/item/card/id/I)
|
|
if(!I)
|
|
if(id && (src in user.contents))
|
|
remove_id(user)
|
|
return TRUE
|
|
else
|
|
var/obj/item/card/id/C = user.get_active_held_item()
|
|
if(istype(C))
|
|
I = C
|
|
|
|
if(I?.registered_name)
|
|
if(!user.transferItemToLoc(I, src))
|
|
return FALSE
|
|
insert_id(I, user)
|
|
update_icon()
|
|
playsound(src, 'sound/machines/button.ogg', 50, 1)
|
|
return TRUE
|
|
|
|
/obj/item/pda/proc/insert_id(obj/item/card/id/inserting_id, mob/user)
|
|
var/obj/old_id = id
|
|
id = inserting_id
|
|
if(ishuman(loc))
|
|
var/mob/living/carbon/human/human_wearer = loc
|
|
if(human_wearer.wear_id == src)
|
|
human_wearer.sec_hud_set_ID()
|
|
if(old_id)
|
|
if(user)
|
|
user.put_in_hands(old_id)
|
|
else
|
|
old_id.forceMove(get_turf(src))
|
|
|
|
// access to status display signals
|
|
/obj/item/pda/attackby(obj/item/C, mob/user, params)
|
|
if(istype(C, /obj/item/cartridge) && !cartridge)
|
|
if(!user.transferItemToLoc(C, src))
|
|
return
|
|
cartridge = C
|
|
cartridge.host_pda = src
|
|
to_chat(user, "<span class='notice'>You insert [cartridge] into [src].</span>")
|
|
update_icon()
|
|
playsound(src, 'sound/machines/button.ogg', 50, 1)
|
|
|
|
else if(istype(C, /obj/item/card/id))
|
|
var/obj/item/card/id/idcard = C
|
|
if(!idcard.registered_name)
|
|
to_chat(user, "<span class='warning'>\The [src] rejects the ID!</span>")
|
|
if (!silent)
|
|
playsound(src, 'sound/machines/terminal_error.ogg', 15, 1)
|
|
return
|
|
|
|
if(!owner)
|
|
owner = idcard.registered_name
|
|
ownjob = idcard.assignment
|
|
update_label()
|
|
to_chat(user, "<span class='notice'>Card scanned.</span>")
|
|
if (!silent)
|
|
playsound(src, 'sound/machines/terminal_success.ogg', 15, 1)
|
|
else
|
|
//Basic safety check. If either both objects are held by user or PDA is on ground and card is in hand.
|
|
if(((src in user.contents) || (isturf(loc) && in_range(src, user))) && (C in user.contents))
|
|
if(!id_check(user, idcard))
|
|
return
|
|
to_chat(user, "<span class='notice'>You put the ID into \the [src]'s slot.</span>")
|
|
updateSelfDialog()//Update self dialog on success.
|
|
return //Return in case of failed check or when successful.
|
|
updateSelfDialog()//For the non-input related code.
|
|
else if(istype(C, /obj/item/paicard) && !pai)
|
|
if(!user.transferItemToLoc(C, src))
|
|
return
|
|
pai = C
|
|
to_chat(user, "<span class='notice'>You slot \the [C] into [src].</span>")
|
|
update_icon()
|
|
updateUsrDialog()
|
|
else if(is_type_in_list(C, contained_item)) //Checks if there is a pen
|
|
if(inserted_item)
|
|
to_chat(user, "<span class='warning'>There is already \a [inserted_item] in \the [src]!</span>")
|
|
return ..()
|
|
else
|
|
if(!user.transferItemToLoc(C, src))
|
|
return
|
|
to_chat(user, "<span class='notice'>You slide \the [C] into \the [src].</span>")
|
|
inserted_item = C
|
|
update_icon()
|
|
playsound(src, 'sound/machines/button.ogg', 50, 1)
|
|
|
|
else if(istype(C, /obj/item/photo))
|
|
var/obj/item/photo/P = C
|
|
picture = P.picture
|
|
to_chat(user, "<span class='notice'>You scan \the [C].</span>")
|
|
else
|
|
return ..()
|
|
|
|
/obj/item/pda/attack(mob/living/carbon/C, mob/living/user)
|
|
if(istype(C))
|
|
switch(scanmode)
|
|
|
|
if(PDA_SCANNER_MEDICAL)
|
|
C.visible_message("<span class='alert'>[user] has analyzed [C]'s vitals!</span>")
|
|
healthscan(user, C, 1)
|
|
add_fingerprint(user)
|
|
|
|
if(PDA_SCANNER_HALOGEN)
|
|
C.visible_message("<span class='warning'>[user] has analyzed [C]'s radiation levels!</span>")
|
|
|
|
user.show_message("<span class='notice'>Analyzing Results for [C]:</span>")
|
|
if(C.radiation)
|
|
user.show_message("\green Radiation Level: \black [C.radiation]")
|
|
else
|
|
user.show_message("<span class='notice'>No radiation detected.</span>")
|
|
|
|
/obj/item/pda/afterattack(atom/A as mob|obj|turf|area, mob/user, proximity)
|
|
. = ..()
|
|
if(!proximity)
|
|
return
|
|
switch(scanmode)
|
|
if(PDA_SCANNER_REAGENT)
|
|
if(!isnull(A.reagents))
|
|
if(A.reagents.reagent_list.len > 0)
|
|
var/reagents_length = A.reagents.reagent_list.len
|
|
to_chat(user, "<span class='notice'>[reagents_length] chemical agent[reagents_length > 1 ? "s" : ""] found.</span>")
|
|
for (var/re in A.reagents.reagent_list)
|
|
to_chat(user, "<span class='notice'>\t [re]</span>")
|
|
else
|
|
to_chat(user, "<span class='notice'>No active chemical agents found in [A].</span>")
|
|
else
|
|
to_chat(user, "<span class='notice'>No significant chemical agents found in [A].</span>")
|
|
|
|
if(PDA_SCANNER_GAS)
|
|
A.analyzer_act(user, src)
|
|
|
|
if (!scanmode && istype(A, /obj/item/paper) && owner)
|
|
var/obj/item/paper/PP = A
|
|
if (!PP.info)
|
|
to_chat(user, "<span class='warning'>Unable to scan! Paper is blank.</span>")
|
|
return
|
|
notehtml = PP.info
|
|
note = replacetext(notehtml, "<BR>", "\[br\]")
|
|
note = replacetext(note, "<li>", "\[*\]")
|
|
note = replacetext(note, "<ul>", "\[list\]")
|
|
note = replacetext(note, "</ul>", "\[/list\]")
|
|
note = html_encode(note)
|
|
notescanned = TRUE
|
|
to_chat(user, "<span class='notice'>Paper scanned. Saved to PDA's notekeeper.</span>" )
|
|
|
|
|
|
/obj/item/pda/proc/explode() //This needs tuning.
|
|
if(!detonatable)
|
|
return
|
|
var/turf/T = get_turf(src)
|
|
|
|
if (ismob(loc))
|
|
var/mob/M = loc
|
|
M.show_message("<span class='userdanger'>Your [src] explodes!</span>", MSG_VISUAL, "<span class='warning'>You hear a loud *pop*!</span>", MSG_AUDIBLE)
|
|
else
|
|
visible_message("<span class='danger'>[src] explodes!</span>", "<span class='warning'>You hear a loud *pop*!</span>")
|
|
|
|
if(T)
|
|
T.hotspot_expose(700,125)
|
|
if(istype(cartridge, /obj/item/cartridge/virus/syndicate))
|
|
explosion(T, -1, 1, 3, 4)
|
|
else
|
|
explosion(T, -1, -1, 2, 3)
|
|
qdel(src)
|
|
return
|
|
|
|
/obj/item/pda/Destroy()
|
|
GLOB.PDAs -= src
|
|
if(istype(id))
|
|
QDEL_NULL(id)
|
|
if(istype(cartridge))
|
|
QDEL_NULL(cartridge)
|
|
if(istype(pai))
|
|
QDEL_NULL(pai)
|
|
if(istype(inserted_item))
|
|
QDEL_NULL(inserted_item)
|
|
return ..()
|
|
|
|
//AI verb and proc for sending PDA messages.
|
|
|
|
/mob/living/silicon/ai/proc/cmd_send_pdamesg(mob/user)
|
|
var/list/plist = list()
|
|
var/list/namecounts = list()
|
|
|
|
if(aiPDA.toff)
|
|
to_chat(user, "Turn on your receiver in order to send messages.")
|
|
return
|
|
|
|
for (var/obj/item/pda/P in get_viewable_pdas())
|
|
if (P == src)
|
|
continue
|
|
else if (P == aiPDA)
|
|
continue
|
|
|
|
plist[avoid_assoc_duplicate_keys(P.owner, namecounts)] = P
|
|
|
|
var/c = input(user, "Please select a PDA") as null|anything in sortList(plist)
|
|
|
|
if (!c)
|
|
return
|
|
|
|
var/selected = plist[c]
|
|
|
|
if(aicamera.stored.len)
|
|
var/add_photo = input(user,"Do you want to attach a photo?","Photo","No") as null|anything in list("Yes","No")
|
|
if(add_photo=="Yes")
|
|
var/datum/picture/Pic = aicamera.selectpicture(user)
|
|
aiPDA.picture = Pic
|
|
|
|
if(incapacitated())
|
|
return
|
|
|
|
aiPDA.create_message(src, selected)
|
|
|
|
|
|
/mob/living/silicon/ai/verb/cmd_toggle_pda_receiver()
|
|
set category = "AI Commands"
|
|
set name = "PDA - Toggle Sender/Receiver"
|
|
if(usr.stat == DEAD)
|
|
return //won't work if dead
|
|
if(!isnull(aiPDA))
|
|
aiPDA.toff = !aiPDA.toff
|
|
to_chat(usr, "<span class='notice'>PDA sender/receiver toggled [(aiPDA.toff ? "Off" : "On")]!</span>")
|
|
else
|
|
to_chat(usr, "You do not have a PDA. You should make an issue report about this.")
|
|
|
|
/mob/living/silicon/ai/verb/cmd_toggle_pda_silent()
|
|
set category = "AI Commands"
|
|
set name = "PDA - Toggle Ringer"
|
|
if(usr.stat == DEAD)
|
|
return //won't work if dead
|
|
if(!isnull(aiPDA))
|
|
//0
|
|
aiPDA.silent = !aiPDA.silent
|
|
to_chat(usr, "<span class='notice'>PDA ringer toggled [(aiPDA.silent ? "Off" : "On")]!</span>")
|
|
else
|
|
to_chat(usr, "You do not have a PDA. You should make an issue report about this.")
|
|
|
|
/mob/living/silicon/ai/proc/cmd_show_message_log(mob/user)
|
|
if(incapacitated())
|
|
return
|
|
if(!isnull(aiPDA))
|
|
var/HTML = "<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8'><title>AI PDA Message Log</title></head><body>[aiPDA.tnote]</body></html>"
|
|
user << browse(HTML, "window=log;size=400x444;border=1;can_resize=1;can_close=1;can_minimize=0")
|
|
else
|
|
to_chat(user, "You do not have a PDA. You should make an issue report about this.")
|
|
|
|
|
|
// Pass along the pulse to atoms in contents, largely added so pAIs are vulnerable to EMP
|
|
/obj/item/pda/emp_act(severity)
|
|
. = ..()
|
|
if (!(. & EMP_PROTECT_CONTENTS))
|
|
for(var/atom/A in src)
|
|
A.emp_act(severity)
|
|
if (!(. & EMP_PROTECT_SELF))
|
|
emped += 1
|
|
spawn(2 * severity)
|
|
emped -= 1
|
|
|
|
/proc/get_viewable_pdas()
|
|
. = list()
|
|
// Returns a list of PDAs which can be viewed from another PDA/message monitor.
|
|
for(var/obj/item/pda/P in GLOB.PDAs)
|
|
if(!P.owner || P.toff || P.hidden)
|
|
continue
|
|
. += P
|
|
|
|
#undef PDA_SCANNER_NONE
|
|
#undef PDA_SCANNER_MEDICAL
|
|
#undef PDA_SCANNER_FORENSICS
|
|
#undef PDA_SCANNER_REAGENT
|
|
#undef PDA_SCANNER_HALOGEN
|
|
#undef PDA_SCANNER_GAS
|
|
#undef PDA_SPAM_DELAY
|
|
|
|
#undef PDA_OVERLAY_ALERT
|
|
#undef PDA_OVERLAY_SCREEN
|
|
#undef PDA_OVERLAY_ID
|
|
#undef PDA_OVERLAY_ITEM
|
|
#undef PDA_OVERLAY_LIGHT
|
|
#undef PDA_OVERLAY_PAI
|