/datum/data/pda/app/messenger name = "Messenger" icon = "comments-o" notify_icon = "comments" title = "SpaceMessenger V4.1.0" template = "pda_messenger" var/toff = 0 //If 1, messenger disabled var/list/tnote = list() //Current Texts var/last_text //No text spamming var/m_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. /datum/data/pda/app/messenger/start() . = ..() unnotify() /datum/data/pda/app/messenger/update_ui(mob/user as mob, list/data) data["silent"] = pda.silent // does the pda make noise when it receives a message? data["toff"] = toff // is the messenger function turned off? // Yes I know convo is awful, but it lets me stay inside the 80 char TGUI line limit data["active_convo"] = active_conversation // Which conversation are we following right now? has_back = active_conversation if(active_conversation) data["messages"] = tnote for(var/c in tnote) if(c["target"] == active_conversation) data["convo_name"] = c["owner"] data["convo_job"] = c["job"] break else var/list/convopdas = list() var/list/pdas = list() for(var/A in GLOB.PDAs) var/obj/item/pda/P = A var/datum/data/pda/app/messenger/PM = P.find_program(/datum/data/pda/app/messenger) if(!P.owner || PM.toff || P == pda || PM.m_hidden) continue if(conversations.Find("[P.UID()]")) convopdas.Add(list(list("Name" = "[P]", "uid" = "[P.UID()]", "Detonate" = "[P.detonate]", "inconvo" = "1"))) else pdas.Add(list(list("Name" = "[P]", "uid" = "[P.UID()]", "Detonate" = "[P.detonate]", "inconvo" = "0"))) data["convopdas"] = convopdas data["pdas"] = pdas var/list/plugins = list() if(pda.cartridge) for(var/A in pda.cartridge.messenger_plugins) var/datum/data/pda/messenger_plugin/P = A plugins += list(list(name = P.name, icon = P.icon, uid = "[P.UID()]")) data["plugins"] = plugins if(pda.cartridge) data["charges"] = pda.cartridge.charges ? pda.cartridge.charges : 0 data["ringtone"] = pda.ttone data["ringtone_list"] = pda.ttone_sound /datum/data/pda/app/messenger/ui_act(action, list/params) if(..()) return unnotify() var/play_beep = TRUE . = TRUE switch(action) if("Toggle Messenger") toff = !toff if("Toggle Ringer")//If viewing texts then erase them, if not then toggle silent status pda.silent = !pda.silent if("Clear")//Clears messages if(params["option"] == "All") tnote.Cut() conversations.Cut() if(params["option"] == "Convo") var/list/new_tnote = list() for(var/i in tnote) if(i["target"] != active_conversation) new_tnote[++new_tnote.len] = i tnote = new_tnote conversations.Remove(active_conversation) active_conversation = null if("Message") play_beep = FALSE var/obj/item/pda/P = locateUID(params["target"]) create_message(usr, P) if(params["target"] in conversations) // Need to make sure the message went through, if not welp. active_conversation = params["target"] if("Select Conversation") var/P = params["target"] for(var/n in conversations) if(P == n) active_conversation = P if("Messenger Plugin") if(!params["target"] || !params["plugin"]) return var/obj/item/pda/P = locateUID(params["target"]) if(!P) to_chat(usr, "PDA not found.") var/datum/data/pda/messenger_plugin/plugin = locateUID(params["plugin"]) if(plugin && (plugin in pda.cartridge.messenger_plugins)) plugin.messenger = src plugin.user_act(usr, P) if("Back") active_conversation = null if(play_beep && !pda.silent) playsound(pda, 'sound/machines/terminal_select.ogg', 15, TRUE) /datum/data/pda/app/messenger/proc/create_message(mob/living/U, obj/item/pda/P) var/t = input(U, "Please enter message", name, null) as text|null if(!t) return t = sanitize(copytext(t, 1, MAX_MESSAGE_LEN)) if(!t || !istype(P)) return if(!in_range(pda, U) && pda.loc != U) return var/datum/data/pda/app/messenger/PM = P.find_program(/datum/data/pda/app/messenger) if(!PM || PM.toff || toff) return if(last_text && world.time < last_text + 5) return if(!pda.can_use()) return last_text = world.time // check if telecomms I/O route 1459 is stable //var/telecomms_intact = telecomms_process(P.owner, owner, t) var/obj/machinery/message_server/useMS = null if(GLOB.message_servers) for(var/A in GLOB.message_servers) var/obj/machinery/message_server/MS = A //PDAs are now dependent on the Message Server. if(MS.active) useMS = MS break var/turf/sender_pos = get_turf(U) var/turf/recipient_pos = get_turf(P) // Can the message be sent var/sendable = FALSE // Can the message be received? var/receivable = FALSE for(var/obj/machinery/tcomms/core/C in GLOB.tcomms_machines) if(C.zlevel_reachable(sender_pos.z)) sendable = TRUE if(C.zlevel_reachable(recipient_pos.z)) receivable = TRUE // Once both are done, exit the loop if(sendable && receivable) break if(!sendable) // Are we in the range of a reciever? to_chat(U, "ERROR: No connection to server.") if(!pda.silent) playsound(pda, 'sound/machines/terminal_error.ogg', 15, TRUE) return if(!receivable) // Is our recipient in the range of a reciever? to_chat(U, "ERROR: No connection to recipient.") if(!pda.silent) playsound(pda, 'sound/machines/terminal_error.ogg', 15, TRUE) return if(useMS && sendable && receivable) // only send the message if its going to work useMS.send_pda_message("[P.owner]","[pda.owner]","[t]") tnote.Add(list(list("sent" = 1, "owner" = "[P.owner]", "job" = "[P.ownjob]", "message" = "[html_decode(t)]", "target" = "[P.UID()]"))) PM.tnote.Add(list(list("sent" = 0, "owner" = "[pda.owner]", "job" = "[pda.ownjob]", "message" = "[html_decode(t)]", "target" = "[pda.UID()]"))) pda.investigate_log("PDA Message - [pda.owner] ([U.key] [ADMIN_PP(U, "PP")]) -> [P.owner] ([ADMIN_VV(P, "VV")]), Message: \"[t]\"", "pda") // Show it to ghosts for(var/mob/M in GLOB.dead_mob_list) if(isobserver(M) && M.client && (M.client.prefs.toggles & PREFTOGGLE_CHAT_GHOSTPDA)) var/ghost_message = "[pda.owner] ([ghost_follow_link(pda, ghost=M)]) PDA Message --> [P.owner] ([ghost_follow_link(P, ghost=M)]): [t]" to_chat(M, "[ghost_message]") if(!conversations.Find("[P.UID()]")) conversations.Add("[P.UID()]") if(!PM.conversations.Find("[pda.UID()]")) PM.conversations.Add("[pda.UID()]") SStgui.update_uis(src) PM.notify("Message from [pda.owner] ([pda.ownjob]), \"[t]\" (Reply)") log_pda("(PDA: [src.name]) sent \"[t]\" to [P.name]", U) var/log_message = "sent PDA message \"[t]\" using [pda]" var/receiver if(ishuman(P.loc)) receiver = P.loc log_message = "[log_message] to [P]" else receiver = P log_message = "[log_message] (no holder)" U.create_log(MISC_LOG, log_message, receiver) if(!pda.silent) playsound(pda, 'sound/machines/terminal_success.ogg', 15, TRUE) else to_chat(U, "ERROR: Messaging server is not responding.") if(!pda.silent) playsound(pda, 'sound/machines/terminal_error.ogg', 15, TRUE) /datum/data/pda/app/messenger/proc/available_pdas() var/list/names = list() var/list/plist = list() var/list/namecounts = list() if(toff) to_chat(usr, "Turn on your receiver in order to send messages.") return for(var/A in GLOB.PDAs) var/obj/item/pda/P = A var/datum/data/pda/app/messenger/PM = P.find_program(/datum/data/pda/app/messenger) if(!P.owner || !PM || PM.hidden || P == pda || PM.toff) continue var/name = P.owner if(name in names) namecounts[name]++ name = "[name] ([namecounts[name]])" else names.Add(name) namecounts[name] = 1 plist[text("[name]")] = P return plist /datum/data/pda/app/messenger/proc/can_receive() return pda.owner && !toff && !hidden // Handler for the in-chat reply button /datum/data/pda/app/messenger/Topic(href, href_list) if(!pda.can_use()) return unnotify() switch(href_list["choice"]) if("Message") var/obj/item/pda/P = locateUID(href_list["target"]) create_message(usr, P) if(href_list["target"] in conversations) // Need to make sure the message went through, if not welp. active_conversation = href_list["target"]