diff --git a/code/__defines/pda.dm b/code/__defines/pda.dm new file mode 100644 index 00000000000..c5d32f03ba8 --- /dev/null +++ b/code/__defines/pda.dm @@ -0,0 +1,3 @@ +#define PDA_APP_UPDATE 0 +#define PDA_APP_NOUPDATE 1 +#define PDA_APP_UPDATE_SLOW 2 diff --git a/code/_helpers/text.dm b/code/_helpers/text.dm index 02a8806089d..a9aac1ffcf5 100644 --- a/code/_helpers/text.dm +++ b/code/_helpers/text.dm @@ -21,6 +21,27 @@ /* * Text sanitization */ +// Can be used almost the same way as normal input for text +/proc/clean_input(Message, Title, Default, mob/user=usr) + var/txt = input(user, Message, Title, Default) as text | null + if(txt) + return html_encode(txt) + +//Simply removes < and > and limits the length of the message +/proc/strip_html_simple(var/t,var/limit=MAX_MESSAGE_LEN) + var/list/strip_chars = list("<",">") + t = copytext(t,1,limit) + for(var/char in strip_chars) + var/index = findtext(t, char) + while(index) + t = copytext(t, 1, index) + copytext(t, index+1) + index = findtext(t, char) + return t + +//Runs byond's sanitization proc along-side strip_html_simple +//I believe strip_html_simple() is required to run first to prevent '<' from displaying as '<' that html_encode() would cause +/proc/adminscrub(var/t,var/limit=MAX_MESSAGE_LEN) + return copytext((html_encode(strip_html_simple(t))),1,limit) //Used for preprocessing entered text /proc/sanitize(var/input, var/max_length = MAX_MESSAGE_LEN, var/encode = 1, var/trim = 1, var/extra = 1) diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index 73b78cb148a..955ccf596a7 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -204,7 +204,9 @@ else P = W itemname = P.name - info = P.notehtml + var/datum/data/pda/app/notekeeper/N = P.find_program(/datum/data/pda/app/notekeeper) + if(N) + info = N.notehtml to_chat(U, "You hold \a [itemname] up to the camera ...") for(var/mob/living/silicon/ai/O in living_mob_list) if(!O.client) diff --git a/code/game/machinery/computer/message.dm b/code/game/machinery/computer/message.dm index 1dc0709ed35..1caa7b61a4d 100644 --- a/code/game/machinery/computer/message.dm +++ b/code/game/machinery/computer/message.dm @@ -131,7 +131,10 @@ //Get out list of viable PDAs var/list/obj/item/device/pda/sendPDAs = list() for(var/obj/item/device/pda/P in PDAs) - if(!P.owner || P.toff || P.hidden) + if(!P.owner || P.hidden) + continue + var/datum/data/pda/app/messenger/M = P.find_program(/datum/data/pda/app/messenger) + if(!M || M.toff) continue sendPDAs["[P.name]"] = "\ref[P]" data["possibleRecipients"] = sendPDAs @@ -265,7 +268,11 @@ if("set_recipient") var/ref = params["val"] var/obj/item/device/pda/P = locate(ref) - if(!istype(P) || !P.owner || P.toff || P.hidden) + if(!istype(P) || !P.owner || P.hidden) + return FALSE + + var/datum/data/pda/app/messenger/M = P.find_program(/datum/data/pda/app/messenger) + if(!M || M.toff) return FALSE customrecepient = P . = TRUE @@ -286,22 +293,26 @@ var/obj/item/device/pda/PDARec = null for(var/obj/item/device/pda/P in PDAs) - if(!P.owner || P.toff || P.hidden) continue + if(!P.owner || P.hidden) + continue + var/datum/data/pda/app/messenger/M = P.find_program(/datum/data/pda/app/messenger) + if(!M || M.toff) + continue if(P.owner == customsender) PDARec = P //Sender isn't faking as someone who exists if(isnull(PDARec)) linkedServer.send_pda_message("[customrecepient.owner]", "[customsender]","[custommessage]") - customrecepient.new_message(customsender, customsender, customjob, custommessage) + var/datum/data/pda/app/messenger/M = customrecepient.find_program(/datum/data/pda/app/messenger) + if(M) + M.receive_message(list("sent" = 0, "owner" = customsender, "job" = customjob, "message" = custommessage), null) //Sender is faking as someone who exists else linkedServer.send_pda_message("[customrecepient.owner]", "[PDARec.owner]","[custommessage]") - customrecepient.tnote.Add(list(list("sent" = 0, "owner" = "[PDARec.owner]", "job" = "[customjob]", "message" = "[custommessage]", "target" ="\ref[PDARec]"))) - - if(!customrecepient.conversations.Find("\ref[PDARec]")) - customrecepient.conversations.Add("\ref[PDARec]") - - customrecepient.new_message(PDARec, custommessage) + + var/datum/data/pda/app/messenger/M = customrecepient.find_program(/datum/data/pda/app/messenger) + if(M) + M.receive_message(list("sent" = 0, "owner" = "[PDARec.owner]", "job" = "[customjob]", "message" = "[custommessage]", "target" = "\ref[PDARec]"), "\ref[PDARec]") //Finally.. ResetMessage() . = TRUE diff --git a/code/game/machinery/newscaster.dm b/code/game/machinery/newscaster.dm index 05e2256d9d0..de85f95e9ac 100644 --- a/code/game/machinery/newscaster.dm +++ b/code/game/machinery/newscaster.dm @@ -101,22 +101,22 @@ NEWSCASTER.newsAlert(annoncement) NEWSCASTER.update_icon() - var/list/receiving_pdas = new - for (var/obj/item/device/pda/P in PDAs) - if(!P.owner) - continue - if(P.toff) - continue - receiving_pdas += P + // var/list/receiving_pdas = new + // for (var/obj/item/device/pda/P in PDAs) + // if(!P.owner) + // continue + // if(P.toff) + // continue + // receiving_pdas += P - spawn(0) // get_receptions sleeps further down the line, spawn of elsewhere - var/datum/receptions/receptions = get_receptions(null, receiving_pdas) // datums are not atoms, thus we have to assume the newscast network always has reception + // spawn(0) // get_receptions sleeps further down the line, spawn of elsewhere + // var/datum/receptions/receptions = get_receptions(null, receiving_pdas) // datums are not atoms, thus we have to assume the newscast network always has reception - for(var/obj/item/device/pda/PDA in receiving_pdas) - if(!(receptions.receiver_reception[PDA] & TELECOMMS_RECEPTION_RECEIVER)) - continue + // for(var/obj/item/device/pda/PDA in receiving_pdas) + // if(!(receptions.receiver_reception[PDA] & TELECOMMS_RECEPTION_RECEIVER)) + // continue - PDA.new_news(annoncement) + // PDA.new_news(annoncement) var/datum/feed_network/news_network = new /datum/feed_network //The global news-network, which is coincidentally a global list. diff --git a/code/game/machinery/pda_multicaster.dm b/code/game/machinery/pda_multicaster.dm index 20e870d3d02..a70f1ede372 100644 --- a/code/game/machinery/pda_multicaster.dm +++ b/code/game/machinery/pda_multicaster.dm @@ -63,7 +63,9 @@ /obj/machinery/pda_multicaster/proc/update_PDAs(var/turn_off) for(var/obj/item/device/pda/pda in contents) - pda.toff = turn_off + var/datum/data/pda/app/messenger/M = pda.find_program(/datum/data/pda/app/messenger/multicast) + if(M) + M.toff = turn_off /obj/machinery/pda_multicaster/proc/update_power() if(toggle) diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm deleted file mode 100644 index 91784b5de6d..00000000000 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ /dev/null @@ -1,1608 +0,0 @@ - -//The advanced pea-green monochrome lcd of tomorrow. - -var/global/list/obj/item/device/pda/PDAs = list() - -/obj/item/device/pda - name = "\improper PDA" - desc = "A portable microcomputer by Thinktronic Systems, LTD. Functionality determined by a preprogrammed ROM cartridge." - icon = 'icons/obj/pda.dmi' - icon_state = "pda" - item_state = "electronic" - w_class = ITEMSIZE_SMALL - slot_flags = SLOT_ID | SLOT_BELT - sprite_sheets = list(SPECIES_TESHARI = 'icons/mob/species/seromi/id.dmi') - - //Main variables - var/pdachoice = 1 - var/owner = null - var/default_cartridge = 0 // Access level defined by cartridge - var/obj/item/weapon/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/lastmode = 0 - var/ui_tick = 0 - var/nanoUI[0] - - //Secondary variables - var/scanmode = 0 //1 is medical scanner, 2 is forensics, 3 is reagent scanner. - var/fon = 0 //Is the flashlight function on? - var/f_lum = 2 //Luminosity for the flashlight function - var/message_silent = 0 //To beep or not to beep, that is the question - var/news_silent = 1 //To beep or not to beep, that is the question. The answer is No. - var/toff = 0 //If 1, messenger disabled - var/tnote[0] //Current Texts - var/last_text //No text spamming - var/last_honk //Also no honk spamming that's bad too - var/ttone = "beep" //The PDA ringtone! - var/newstone = "beep, beep" //The news ringtone! - var/lock_code = "" // Lockcode to unlock uplink - 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!" //Current note in the notepad function - var/notehtml = "" - var/cart = "" //A place to stick cartridge menu information - var/detonate = 1 // Can the PDA be blown up? - var/hidden = 0 // Is the PDA hidden from the PDA list? - var/active_conversation = null // New variable that allows us to only view a single conversation. - var/list/conversations = list() // For keeping up with who we have PDA messsages from. - var/new_message = 0 //To remove hackish overlay check - var/new_news = 0 - var/touch_silent = 0 //If 1, no beeps on interacting. - - var/active_feed // The selected feed - var/list/warrant // The warrant as we last knew it - var/list/feeds = list() // The list of feeds as we last knew them - var/list/feed_info = list() // The data and contents of each feed as we last knew them - - var/list/cartmodes = list(40, 42, 43, 433, 44, 441, 45, 451, 46, 48, 47, 49) // If you add more cartridge modes add them to this list as well. - var/list/no_auto_update = list(1, 40, 43, 44, 441, 45, 451) // These modes we turn off autoupdate - var/list/update_every_five = list(3, 41, 433, 46, 47, 48, 49) // These we update every 5 ticks - - var/obj/item/weapon/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 - this is assignment (potentially alt title) - var/ownrank = null // this one is rank, never alt title - - var/obj/item/device/paicard/pai = null // A slot for a personal AI device - - var/spam_proof = FALSE // If true, it can't be spammed by random events. - -/obj/item/device/pda/examine(mob/user) - . = ..() - if(Adjacent(user)) - . += "The time [stationtime2text()] is displayed in the corner of the screen." - -/obj/item/device/pda/CtrlClick() - if(issilicon(usr)) - return - - if(can_use(usr)) - remove_pen() - return - ..() - -/obj/item/device/pda/AltClick() - if(issilicon(usr)) - return - - if ( can_use(usr) ) - if(id) - remove_id() - else - to_chat(usr, "This PDA does not have an ID in it.") - -//Bloop when using: -/obj/item/device/pda/CouldUseTopic(var/mob/user) - ..() - if(iscarbon(user) && !touch_silent) - playsound(src, 'sound/machines/pda_click.ogg', 20) - -/obj/item/device/pda/medical - default_cartridge = /obj/item/weapon/cartridge/medical - icon_state = "pda-m" - -/obj/item/device/pda/viro - default_cartridge = /obj/item/weapon/cartridge/medical - icon_state = "pda-v" - -/obj/item/device/pda/engineering - default_cartridge = /obj/item/weapon/cartridge/engineering - icon_state = "pda-e" - -/obj/item/device/pda/security - default_cartridge = /obj/item/weapon/cartridge/security - icon_state = "pda-s" - -/obj/item/device/pda/detective - default_cartridge = /obj/item/weapon/cartridge/detective - icon_state = "pda-det" - -/obj/item/device/pda/warden - default_cartridge = /obj/item/weapon/cartridge/security - icon_state = "pda-warden" - -/obj/item/device/pda/janitor - default_cartridge = /obj/item/weapon/cartridge/janitor - icon_state = "pda-j" - ttone = "slip" - -/obj/item/device/pda/science - default_cartridge = /obj/item/weapon/cartridge/signal/science - icon_state = "pda-tox" - ttone = "boom" - -/obj/item/device/pda/clown - default_cartridge = /obj/item/weapon/cartridge/clown - icon_state = "pda-clown" - desc = "A portable microcomputer by Thinktronic Systems, LTD. The surface is coated with polytetrafluoroethylene and banana drippings." - ttone = "honk" - -/obj/item/device/pda/mime - default_cartridge = /obj/item/weapon/cartridge/mime - icon_state = "pda-mime" - message_silent = 1 - news_silent = 1 - ttone = "silence" - newstone = "silence" - -/obj/item/device/pda/heads - default_cartridge = /obj/item/weapon/cartridge/head - icon_state = "pda-h" - news_silent = 1 - -/obj/item/device/pda/heads/hop - default_cartridge = /obj/item/weapon/cartridge/hop - icon_state = "pda-hop" - -/obj/item/device/pda/heads/hos - default_cartridge = /obj/item/weapon/cartridge/hos - icon_state = "pda-hos" - -/obj/item/device/pda/heads/ce - default_cartridge = /obj/item/weapon/cartridge/ce - icon_state = "pda-ce" - -/obj/item/device/pda/heads/cmo - default_cartridge = /obj/item/weapon/cartridge/cmo - icon_state = "pda-cmo" - -/obj/item/device/pda/heads/rd - default_cartridge = /obj/item/weapon/cartridge/rd - icon_state = "pda-rd" - -/obj/item/device/pda/captain - default_cartridge = /obj/item/weapon/cartridge/captain - icon_state = "pda-c" - detonate = 0 - //toff = 1 - -/obj/item/device/pda/ert - default_cartridge = /obj/item/weapon/cartridge/captain - icon_state = "pda-h" - detonate = 0 -// hidden = 1 - -/obj/item/device/pda/cargo - default_cartridge = /obj/item/weapon/cartridge/quartermaster - icon_state = "pda-cargo" - -/obj/item/device/pda/quartermaster - default_cartridge = /obj/item/weapon/cartridge/quartermaster - icon_state = "pda-q" - -/obj/item/device/pda/shaftminer - icon_state = "pda-miner" - default_cartridge = /obj/item/weapon/cartridge/miner - -/obj/item/device/pda/syndicate - default_cartridge = /obj/item/weapon/cartridge/syndicate - icon_state = "pda-syn" -// name = "Military PDA" // Vorestation Edit -// owner = "John Doe" - hidden = 1 - -/obj/item/device/pda/chaplain - default_cartridge = /obj/item/weapon/cartridge/service - icon_state = "pda-holy" - ttone = "holy" - -/obj/item/device/pda/lawyer - default_cartridge = /obj/item/weapon/cartridge/lawyer - icon_state = "pda-lawyer" - ttone = "..." - -/obj/item/device/pda/botanist - default_cartridge = /obj/item/weapon/cartridge/service - icon_state = "pda-hydro" - -/obj/item/device/pda/roboticist - default_cartridge = /obj/item/weapon/cartridge/signal/science - icon_state = "pda-robot" - -/obj/item/device/pda/librarian - default_cartridge = /obj/item/weapon/cartridge/service - icon_state = "pda-libb" - desc = "A portable microcomputer by Thinktronic Systems, LTD. This is model is a WGW-11 series e-reader." - note = "Congratulations, your station has chosen the Thinktronic 5290 WGW-11 Series E-reader and Personal Data Assistant!" - message_silent = 1 //Quiet in the library! - news_silent = 0 // Librarian is above the law! (That and alt job title is reporter) - -/obj/item/device/pda/clear - icon_state = "pda-transp" - desc = "A portable microcomputer by Thinktronic Systems, LTD. This is model is a special edition with a transparent case." - note = "Congratulations, you have chosen the Thinktronic 5230 Personal Data Assistant Deluxe Special Max Turbo Limited Edition!" - -/obj/item/device/pda/chef - default_cartridge = /obj/item/weapon/cartridge/service - icon_state = "pda-chef" - -/obj/item/device/pda/bar - default_cartridge = /obj/item/weapon/cartridge/service - icon_state = "pda-bar" - -/obj/item/device/pda/atmos - default_cartridge = /obj/item/weapon/cartridge/atmos - icon_state = "pda-atmo" - -/obj/item/device/pda/chemist - default_cartridge = /obj/item/weapon/cartridge/chemistry - icon_state = "pda-chem" - -/obj/item/device/pda/geneticist - default_cartridge = /obj/item/weapon/cartridge/medical - icon_state = "pda-gene" - - -// Special AI/pAI PDAs that cannot explode. -/obj/item/device/pda/ai - icon_state = "NONE" - ttone = "data" - newstone = "news" - detonate = 0 - - -/obj/item/device/pda/ai/proc/set_name_and_job(newname as text, newjob as text, newrank as null|text) - owner = newname - ownjob = newjob - if(newrank) - ownrank = newrank - else - ownrank = ownjob - name = newname + " (" + ownjob + ")" - -//AI verb and proc for sending PDA messages. -/obj/item/device/pda/ai/verb/cmd_send_pdamesg() - set category = "AI IM" - set name = "Send Message" - set src in usr - if(usr.stat == 2) - to_chat(usr, "You can't send PDA messages because you are dead!") - return - var/list/plist = available_pdas() - if (plist) - var/c = input(usr, "Please select a PDA") as null|anything in sortList(plist) - if (!c) // if the user hasn't selected a PDA file we can't send a message - return - var/selected = plist[c] - create_message(usr, selected, 0) - -/obj/item/device/pda/ai/verb/cmd_toggle_pda_receiver() - set category = "AI IM" - set name = "Toggle Sender/Receiver" - set src in usr - if(usr.stat == 2) - to_chat(usr, "You can't send PDA messages because you are dead!") - return - toff = !toff - to_chat(usr, "PDA sender/receiver toggled [(toff ? "Off" : "On")]!") - -/obj/item/device/pda/ai/verb/cmd_toggle_pda_silent() - set category = "AI IM" - set name = "Toggle Ringer" - set src in usr - if(usr.stat == 2) - to_chat(usr, "You can't send PDA messages because you are dead!") - return - message_silent=!message_silent - to_chat(usr, "PDA ringer toggled [(message_silent ? "Off" : "On")]!") - -/obj/item/device/pda/ai/verb/cmd_show_message_log() - set category = "AI IM" - set name = "Show Message Log" - set src in usr - if(usr.stat == 2) - to_chat(usr, "You can't send PDA messages because you are dead!") - return - var/HTML = "
| Area | Cell % | Load - {{for data.records.sensor_reading.apc_data}} - |
|---|---|---|
| {{:value.name}} - | {{:value.cell_charge}}% - | {{:value.total_load}} - {{empty}} - |
| No APCs found! - {{/for}} - |
