diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index e5687ba2050..1257c494746 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -137,18 +137,7 @@ useMS.send_pda_message("[P.owner]", "[command_name()] Payroll", msg) var/datum/data/pda/app/messenger/PM = P.find_program(/datum/data/pda/app/messenger) - if(PM) - PM.play_ringtone() - //Search for holder of the PDA. - var/mob/living/L = null - if(P.loc && isliving(P.loc)) - L = P.loc - //Maybe they are a pAI! - else - L = get(P, /mob/living/silicon) - - if(L) - L << "\icon[P] Message from [command_name()] (Payroll), \"[msg]\" (Unable to Reply)" + PM.notify("Message from [command_name()] (Payroll), \"[msg]\" (Unable to Reply)", 0) break /datum/game_mode/proc/check_finished() //to be called by ticker diff --git a/code/game/gamemodes/mutiny/mutiny.dm b/code/game/gamemodes/mutiny/mutiny.dm index 113cffa46c0..e3edc521f33 100644 --- a/code/game/gamemodes/mutiny/mutiny.dm +++ b/code/game/gamemodes/mutiny/mutiny.dm @@ -107,9 +107,7 @@ datum/game_mode/mutiny var/datum/data/pda/app/messenger/pdam = pda.find_program(/datum/data/pda/app/messenger) if(pdam) - pdam.play_ringtone() - - head_mutineer.current << fluff.get_pda_body() + pdam.notify(fluff.get_pda_body(), 0) return 1 proc/get_equipment_slots() diff --git a/code/game/machinery/computer/message.dm b/code/game/machinery/computer/message.dm index 85d4807b355..75c9974bfbb 100644 --- a/code/game/machinery/computer/message.dm +++ b/code/game/machinery/computer/message.dm @@ -22,17 +22,18 @@ var/defaultmsg = "Welcome. Please select an option." var/rebootmsg = "%$&(£: Critical %$$@ Error // !RestArting! - ?pLeaSe wAit!" //Computer properties - var/screen = 0 // 0 = Main menu, 1 = Message Logs, 2 = Hacked screen, 3 = Custom Message + var/screen = 0 // 0 = Main menu, 1 = Message Logs, 2 = Hacked screen, 3 = Custom Message, 4 = chat room selection, 5 = chat room logs var/hacking = 0 // Is it being hacked into by the AI/Cyborg var/emag = 0 // When it is emagged. var/message = "System bootup complete. Please select an option." // The message that shows on the main menu. var/auth = 0 // Are they authenticated? - var/optioncount = 7 + var/optioncount = 8 // Custom Message Properties var/customsender = "System Administrator" var/obj/item/device/pda/customrecepient = null var/customjob = "Admin" var/custommessage = "This is a test, please ignore." + var/datum/chatroom/current_chatroom = null light_color = LIGHT_COLOR_DARKGREEN @@ -130,6 +131,7 @@ dat += "
[++i]. Clear Request Console Logs
" dat += "
[++i]. Set Custom Key
" dat += "
[++i]. Send Admin Message
" + dat += "
[++i]. View Chatrooms
" else for(var/n = ++i; n <= optioncount; n++) dat += "
[n]. ---------------
" @@ -247,7 +249,41 @@ dat += {"
X
[rc.send_dpt] [rc.rec_dpt][rc.message][rc.stamp][rc.id_auth][rc.priority]"} dat += "" - + //Chat room list + if(5) + dat += "
Back - Refresh

" + dat += {" + + + + + + "} + for(var/datum/chatroom/C in chatrooms) + var/list/invites = (C.invites - C.users) + dat += {" + + + + + "} + dat += "
Room NameUsersInvitesMessages
[C.name][C.users.len][invites.len][C.logs.len]
" + //View chat room logs + if(6) + dat += "
Back - Refresh

" + dat += {" + + + + "} + if(current_chatroom) + for(var/M in current_chatroom.logs) + var/list/message = M + dat += {" + + + "} + dat += "
NameMessage
[message["username"]][message["message"]]
" dat += "" message = defaultmsg @@ -459,12 +495,8 @@ //Sender isn't faking as someone who exists if(isnull(PDARec)) src.linkedServer.send_pda_message("[customrecepient.owner]", "[customsender]","[custommessage]") - recipient_messenger.play_ringtone() - if( customrecepient.loc && ishuman(customrecepient.loc) ) - var/mob/living/carbon/human/H = customrecepient.loc - H << "\icon[customrecepient] Message from [customsender] ([customjob]), \"[custommessage]\" (
Reply)" + recipient_messenger.notify("Message from [customsender] ([customjob]), \"[custommessage]\" (Reply)") log_pda("[usr] (PDA: [customsender]) sent \"[custommessage]\" to [customrecepient.owner]") - recipient_messenger.set_new(1) //Sender is faking as someone who exists else src.linkedServer.send_pda_message("[customrecepient.owner]", "[PDARec.owner]","[custommessage]") @@ -473,12 +505,8 @@ if(!recipient_messenger.conversations.Find("\ref[PDARec]")) recipient_messenger.conversations.Add("\ref[PDARec]") - recipient_messenger.play_ringtone() - if( customrecepient.loc && ishuman(customrecepient.loc) ) - var/mob/living/carbon/human/H = customrecepient.loc - H << "\icon[customrecepient] Message from [PDARec.owner] ([customjob]), \"[custommessage]\" (Reply)" + recipient_messenger.notify("Message from [PDARec.owner] ([customjob]), \"[custommessage]\" (Reply)") log_pda("[usr] (PDA: [PDARec.owner]) sent \"[custommessage]\" to [customrecepient.owner]") - recipient_messenger.set_new(1) //Finally.. ResetMessage() @@ -494,6 +522,19 @@ if (href_list["back"]) src.screen = 0 + // View chat room list + if (href_list["chatroom"]) + if(!linkedServer || (linkedServer.stat & (NOPOWER|BROKEN))) + message = noserver + else if(auth) + screen = 5 + if (href_list["viewroom"]) + if(!linkedServer || (linkedServer.stat & (NOPOWER|BROKEN))) + message = noserver + else if(auth) + current_chatroom = locate(href_list["viewroom"]) + if(current_chatroom) + screen = 6 return src.attack_hand(usr) diff --git a/code/modules/events/money_spam.dm b/code/modules/events/money_spam.dm index 37a29a00bbd..94f27958b9b 100644 --- a/code/modules/events/money_spam.dm +++ b/code/modules/events/money_spam.dm @@ -103,17 +103,4 @@ if(ai.aiPDA != P && ai.aiPDA != src) ai.show_message("Intercepted message from [sender] (Unknown / spam?) to [P:owner]: [message]") - //Commented out because we don't send messages like this anymore. Instead it will just popup in their chat window. - //P.tnote += "← From [sender] (Unknown / spam?):
[message]
" - - PM.play_ringtone() - //Search for holder of the PDA. - var/mob/living/L = null - if(P.loc && isliving(P.loc)) - L = P.loc - //Maybe they are a pAI! - else - L = get(P, /mob/living/silicon) - - if(L) - L << "\icon[P] Message from [sender] (Unknown / spam?), \"[message]\" (Unable to Reply)" + PM.notify("Message from [sender] (Unknown / spam?), \"[message]\" (Unable to Reply)", 0) \ No newline at end of file diff --git a/code/modules/mob/living/silicon/pai/software_modules.dm b/code/modules/mob/living/silicon/pai/software_modules.dm index 5278300ffb5..46d227399de 100644 --- a/code/modules/mob/living/silicon/pai/software_modules.dm +++ b/code/modules/mob/living/silicon/pai/software_modules.dm @@ -149,7 +149,7 @@ return data["receiver_off"] = M.toff - data["ringer_off"] = M.silent + data["ringer_off"] = M.notify_silent data["current_ref"] = null data["current_name"] = user.current_pda_messaging @@ -205,7 +205,7 @@ M.toff = href_list["toggler"] != "1" return 1 else if(href_list["ringer"]) - M.silent = href_list["ringer"] != "1" + M.notify_silent = href_list["ringer"] != "1" return 1 else if(href_list["select"]) var/s = href_list["select"] diff --git a/code/modules/ninja/suit/SpiderOS.dm b/code/modules/ninja/suit/SpiderOS.dm index 11a595e6645..b44eab056ee 100644 --- a/code/modules/ninja/suit/SpiderOS.dm +++ b/code/modules/ninja/suit/SpiderOS.dm @@ -220,19 +220,9 @@ display_to << "Error: unable to deliver message." display_spideros() return - //Search for holder of the PDA. - var/mob/living/L = null - if(P.loc && isliving(P.loc)) - L = P.loc - //Maybe they are a pAI! - else - L = get(P, /mob/living/silicon) - - if(L) - L << "\icon[P] Message from unknown source: \"[t]\" (Unable to Reply)" - P.play_ringtone() + var/datum/data/pda/app/messenger/M = P.find_program(/datum/data/pda/app/messenger) - M.set_new(1) + M.notify("Message from unknown source: \"[t]\" (Unable to Reply)", 0) if("Inject") if( (href_list["tag"]=="radium"? (reagents.get_reagent_amount("radium"))<=(a_boost*a_transfer) : !reagents.get_reagent_amount(href_list["tag"])) )//Special case for radium. If there are only a_boost*a_transfer radium units left. diff --git a/code/modules/pda/PDA.dm b/code/modules/pda/PDA.dm index c88dce0e20f..dd900fca122 100755 --- a/code/modules/pda/PDA.dm +++ b/code/modules/pda/PDA.dm @@ -29,19 +29,27 @@ var/global/list/obj/item/device/pda/PDAs = list() 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/detonate = 1 // Can the PDA be blown up? - var/newmessage = 0 //To remove hackish overlay check var/ttone = "beep" //The ringtone! + var/list/ttone_sound = list("beep" = 'sound/machines/twobeep.ogg', + "boom" = 'sound/effects/explosionfar.ogg', + "slip" = 'sound/misc/slip.ogg', + "honk" = 'sound/items/bikehorn.ogg', + "SKREE" = 'sound/voice/shriek1.ogg', + "holy" = 'sound/items/PDA/ambicha4-short.ogg', + "xeno" = 'sound/voice/hiss1.ogg') var/list/programs = list( new/datum/data/pda/app/main_menu, new/datum/data/pda/app/notekeeper, new/datum/data/pda/app/messenger, new/datum/data/pda/app/manifest, + new/datum/data/pda/app/chatroom, new/datum/data/pda/app/atmos_scanner, new/datum/data/pda/utility/scanmode/notes, new/datum/data/pda/utility/flashlight) var/list/shortcut_cache = list() var/list/shortcut_cat_order = list() + var/list/notifying_programs = list() 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 @@ -133,7 +141,7 @@ var/global/list/obj/item/device/pda/PDAs = list() cat = list() shortcut_cache[P.category] = cat shortcut_cat_order += P.category - cat |= list(list(name = P.name, icon = P.icon, ref = "\ref[P]")) + cat |= list(list(name = P.name, icon = P.icon, notify_icon = P.notify_icon, ref = "\ref[P]")) // force the order of a few core categories shortcut_cat_order = list("General") \ @@ -250,12 +258,17 @@ var/global/list/obj/item/device/pda/PDAs = list() start_program(find_program(/datum/data/pda/app/main_menu)) if(C.radio) C.radio.hostpda = null + for(var/datum/data/pda/P in notifying_programs) + if(P in C.programs) + P.unnotify() cartridge = null update_shortcuts() if ("Authenticate")//Checks for ID id_check(usr, 1) if("Retro") retro_mode = !retro_mode + if("Ringtone") + return set_ringtone() else if(current_app) . = current_app.Topic(href, href_list) @@ -281,6 +294,8 @@ var/global/list/obj/item/device/pda/PDAs = list() if(can_use(usr)) start_program(find_program(/datum/data/pda/app/main_menu)) + notifying_programs.Cut() + overlays.Cut() usr << "You press the reset button on \the [src]." else usr << "You cannot do this while restrained." @@ -442,4 +457,30 @@ var/global/list/obj/item/device/pda/PDAs = list() // Pass along the pulse to atoms in contents, largely added so pAIs are vulnerable to EMP /obj/item/device/pda/emp_act(severity) for(var/atom/A in src) - A.emp_act(severity) \ No newline at end of file + A.emp_act(severity) + +/obj/item/device/pda/proc/play_ringtone() + var/S + + if(ttone in ttone_sound) + S = ttone_sound[ttone] + else + S = 'sound/machines/twobeep.ogg' + playsound(loc, S, 50, 1) + for(var/mob/O in hearers(3, loc)) + O.show_message(text("\icon[src] *[ttone]*")) + +/obj/item/device/pda/proc/set_ringtone() + var/t = input("Please enter new ringtone", name, ttone) as text + if (in_range(src, usr) && loc == usr) + if (t) + if(hidden_uplink && hidden_uplink.check_trigger(usr, lowertext(t), lowertext(lock_code))) + usr << "The PDA softly beeps." + close(usr) + else + t = sanitize(copytext(t, 1, 20)) + ttone = t + return 1 + else + close(usr) + return 0 \ No newline at end of file diff --git a/code/modules/pda/ai.dm b/code/modules/pda/ai.dm index a6c7769ab52..135ff0d6431 100644 --- a/code/modules/pda/ai.dm +++ b/code/modules/pda/ai.dm @@ -17,7 +17,7 @@ set category = "AI IM" set name = "Send PDA Message" set src in usr - + if(usr.stat == DEAD) usr << "You can't send PDA messages because you are dead!" return @@ -36,7 +36,7 @@ set category = "AI IM" set name = "Show Message Log" set src in usr - + if(usr.stat == DEAD) usr << "You can't do that because you are dead!" return @@ -56,7 +56,7 @@ set category = "AI IM" set name = "Toggle Sender/Receiver" set src in usr - + if(usr.stat == DEAD) usr << "You can't do that because you are dead!" return @@ -69,13 +69,13 @@ set category = "AI IM" set name = "Toggle Ringer" set src in usr - + if(usr.stat == DEAD) usr << "You can't do that because you are dead!" return var/datum/data/pda/app/messenger/M = find_program(/datum/data/pda/app/messenger) - M.silent = !M.silent - usr << "PDA ringer toggled [(M.silent ? "Off" : "On")]!" + M.notify_silent = !M.notify_silent + usr << "PDA ringer toggled [(M.notify_silent ? "Off" : "On")]!" /obj/item/device/pda/ai/can_use() return 1 diff --git a/code/modules/pda/app.dm b/code/modules/pda/app.dm index 1f8b37d97fa..58403d108a9 100644 --- a/code/modules/pda/app.dm +++ b/code/modules/pda/app.dm @@ -1,6 +1,8 @@ // Base class for anything that can show up on home screen /datum/data/pda var/icon = "tasks" + var/notify_icon = "exclamation-circle" + var/notify_silent = 0 var/hidden = 0 // program not displayed in main menu var/category = "General" // the category to list it in on the main menu var/obj/item/device/pda/pda // if this is null, and the app is running code, something's gone wrong @@ -11,6 +13,35 @@ /datum/data/pda/proc/start() +/datum/data/pda/proc/notify(message, blink = 1) + if(message) + //Search for holder of the PDA. + var/mob/living/L = null + if(pda.loc && isliving(pda.loc)) + L = pda.loc + //Maybe they are a pAI! + else + L = get(pda, /mob/living/silicon) + + if(L) + L << "\icon[pda] [message]" + nanomanager.update_user_uis(L, pda) // Update the receiving user's PDA UI so that they can see the new message + + if(!notify_silent) + pda.play_ringtone() + + if(blink && !(src in pda.notifying_programs)) + pda.overlays.Cut() + pda.overlays += image('icons/obj/pda.dmi', "pda-r") + pda.notifying_programs |= src + +/datum/data/pda/proc/unnotify() + if(src in pda.notifying_programs) + pda.notifying_programs -= src + if(!pda.notifying_programs.len) + pda.overlays.Cut() + +/datum/data/pda/proc/ // An app has a button on the home screen and its own UI /datum/data/pda/app diff --git a/code/modules/pda/chatroom.dm b/code/modules/pda/chatroom.dm index 008dab64149..714f294d235 100644 --- a/code/modules/pda/chatroom.dm +++ b/code/modules/pda/chatroom.dm @@ -1,16 +1,252 @@ -var/list/chatrooms = list() +var/list/chatrooms = list(new /datum/chatroom("General Discussion")) /datum/chatroom var/name = "Generic Chatroom" - var/list/logged_in = list() + var/list/users = list() + var/list/invites = list() var/list/logs = list() // chat logs - var/list/banned = list() // banned users - var/list/whitelist = list() // whitelisted users - var/list/muted = list() - var/topic = "" // topic message for the chatroom - var/password = "" // blank for no password. - var/operator = "" // name of the operator + var/topic = "Discussion" // topic message for the chatroom + var/is_public = 1 + var/announcer = "CyberiadAI" -/datum/chatroom/proc/attempt_connect(var/obj/item/device/pda/device, var/obj/password) - if(!device) +/datum/chatroom/New(n) + name = n + +/datum/chatroom/proc/post(user, message, username) + if(!user || !message) return + + if(!username) + if(istype(user, /datum/data/pda/app/chatroom)) + var/datum/data/pda/app/chatroom/c = user + if(!c.pda.owner) + return + username = c.pda.owner + else + return + + logs += list(list(username = username, message = message)) + + for(var/datum/data/pda/app/chatroom/u in users) + if(!u.toff && user != u) + u.notify("Post from [username] in #[name], \"[message]\" (Post)") + +/datum/chatroom/proc/announce(user, message) + post(user, "[message]", announcer) + +/datum/chatroom/proc/login(datum/data/pda/app/chatroom/user) + if(!user || !user.pda.owner) + return 0 + + if(user in users) + return 1 + + if(!is_public && !(user in invites)) + return 0 + + users += user + announce(user, "[user.pda.owner] has entered #[name].") + return 1 + +/datum/chatroom/proc/logout(datum/data/pda/app/chatroom/user) + if(!user || !user.pda.owner || !(user in users)) + return + + users -= user + invites -= user + announce(user, "[user.pda.owner] has left #[name].") + +/datum/data/pda/app/chatroom + name = "Chatbuddy" + icon = "hashtag" + notify_icon = "comments" + template = "pda_chatroom" + var/toff = 0 + var/datum/chatroom/current_room = null + var/inviting = 0 + var/channels_created = 0 + var/max_channels_created = 3 + var/latest_post = 0 + var/auto_scroll = 1 + +/datum/data/pda/app/chatroom/start() + . = ..() + unnotify() + latest_post = 0 + +/datum/data/pda/app/chatroom/update_ui(mob/user as mob, list/data) + data["silent"] = notify_silent + data["toff"] = toff + if(!messaging_available()) + data["no_server"] = 1 + has_back = 0 + else if(current_room) + data["room"] = current_room.name + data["topic"] = current_room.topic + if(inviting) + data["inviting"] = 1 + var/list/pdas = list() + for(var/A in PDAs) + var/obj/item/device/pda/P = A + var/datum/data/pda/app/chatroom/C = P.find_program(/datum/data/pda/app/chatroom) + var/datum/data/pda/app/messenger/PM = P.find_program(/datum/data/pda/app/messenger) + + if (!P.owner || P == pda || PM.m_hidden || (C in current_room.invites) || (C in current_room.users)) + continue + pdas += list(list(name = "[P.owner] ([P.ownjob])", ref = "\ref[C]")) + data["people"] = pdas + else + data["history"] = current_room.logs + var/list/users[0] + for(var/U in current_room.users) + var/datum/data/pda/app/chatroom/ch = U + users += "[ch.pda.owner]" + for(var/U in (current_room.invites - current_room.users)) + var/datum/data/pda/app/chatroom/ch = U + users += "[ch.pda.owner]" + data["users"] = users + data["auto_scroll"] = auto_scroll + data["latest_post"] = latest_post + latest_post = current_room.logs.len + has_back = 1 + else + var/list/rooms[0] + for(var/datum/chatroom/c in chatrooms) + if((src in c.users) || (src in c.invites) || c.is_public) + rooms += list(list(name = "[c]", ref = "\ref[c]")) + data["rooms"] = rooms + has_back = 0 + +/datum/data/pda/app/chatroom/proc/messaging_available() + if(message_servers) + for(var/A in message_servers) + var/obj/machinery/message_server/MS = A + if(MS.active) + return 1 + return 0 + +/datum/data/pda/app/chatroom/proc/check_messaging_available() + . = messaging_available() + if(!.) + usr << "ERROR: Messaging server is not responding." + +/datum/data/pda/app/chatroom/Topic(href, list/href_list) + unnotify() + + switch(href_list["choice"]) + if("Toggle Chatroom") + toff = !toff + if("Toggle Ringer") + notify_silent = !notify_silent + if("Back") + if(inviting) + inviting = 0 + else + current_room = null + latest_post = 0 + if("Join") + if(!check_messaging_available()) + return + + if(href_list["room"]) + current_room = locate(href_list["room"]) + if(!(src in current_room.users)) + if(!current_room.login(src)) + current_room = null + latest_post = 0 + if("Post") + if(!check_messaging_available()) + return + + var/datum/chatroom/target + if(href_list["target"]) + target = locate(href_list["target"]) + else + target = current_room + + if(!target) + return + + var/t = input("Please enter message", target) as text|null + if(!t) + return + t = sanitize(copytext(t, 1, MAX_MESSAGE_LEN)) + t = readd_quotes(t) + if (!t || (!in_range(pda, usr) && pda.loc != usr)) + return + + target.post(src, t) + if("Topic") + if(!check_messaging_available() || !current_room) + return + + var/t = input("Enter new topic:", current_room, current_room.topic) as text|null + if(!t) + return + t = sanitize(copytext(t, 1, MAX_MESSAGE_LEN)) + t = readd_quotes(t) + if (!t || (!in_range(pda, usr) && pda.loc != usr)) + return + + current_room.topic = t + current_room.announce(src, "Topic has been changed to '[t]' by [pda.owner].") + if("Leave") + if(!current_room) + return + + current_room.logout(src) + current_room = null + latest_post = 0 + if("Invite") + if(!check_messaging_available() || !current_room) + return + + inviting = 1 + if("Invite PDA") + if(!check_messaging_available() || !current_room || !href_list["user"]) + return + + var/datum/data/pda/app/chatroom/C = locate(href_list["user"]) + if(C) + current_room.invites += C + if(!C.toff) + C.notify("Invite to #[current_room] (Join)") + if("New Room") + if(!check_messaging_available()) + return + + if(channels_created >= max_channels_created) + alert("This PDA has already reached its maximum channels created.", name) + return + + var/t = input("Enter room name:", name) as text|null + if(!t) + return + t = sanitize(copytext(t, 1, MAX_NAME_LEN)) + t = readd_quotes(t) + + var/access = input("Room access?", current_room) as null|anything in list("Public", "Private") + if(!access) + return + + if (!t || (!in_range(pda, usr) && pda.loc != usr)) + return + + // check if already taken + for(var/datum/chatroom/C in chatrooms) + if(C.name == t) + alert("Channel with that name already exists.", name) + return + + channels_created++ + current_room = new /datum/chatroom(t) + chatrooms += current_room + latest_post = 0 + + current_room.invites += src + current_room.is_public = access == "Public" + current_room.login(src) + if(!current_room.is_public) + current_room.announce(src, "Users must be invited to join this room.") + if("Autoscroll") + auto_scroll = !auto_scroll \ No newline at end of file diff --git a/code/modules/pda/core_apps.dm b/code/modules/pda/core_apps.dm index 55a6dbd6f45..0117a6b9140 100644 --- a/code/modules/pda/core_apps.dm +++ b/code/modules/pda/core_apps.dm @@ -11,6 +11,11 @@ data["apps"] = pda.shortcut_cache data["categories"] = pda.shortcut_cat_order data["pai"] = !isnull(pda.pai) // pAI inserted? + + var/list/notifying[0] + for(var/P in pda.notifying_programs) + notifying["\ref[P]"] = 1 + data["notifying"] = notifying /datum/data/pda/app/main_menu/Topic(href, list/href_list) switch(href_list["choice"]) diff --git a/code/modules/pda/messenger.dm b/code/modules/pda/messenger.dm index 0cd76bb7796..6e87f13dc26 100644 --- a/code/modules/pda/messenger.dm +++ b/code/modules/pda/messenger.dm @@ -1,82 +1,76 @@ /datum/data/pda/app/messenger name = "Messenger" icon = "comments-o" - title = "SpaceMessenger V4.0.1" + notify_icon = "comments" + title = "SpaceMessenger V4.1.0" template = "pda_messenger" - var/silent = 0 //To beep or not to beep, that is the question var/toff = 0 //If 1, messenger disabled var/list/tnote[0] //Current Texts var/last_text //No text spamming - var/list/ttone_sound = list("beep" = 'sound/machines/twobeep.ogg', - "boom" = 'sound/effects/explosionfar.ogg', - "slip" = 'sound/misc/slip.ogg', - "honk" = 'sound/items/bikehorn.ogg', - "SKREE" = 'sound/voice/shriek1.ogg', - "holy" = 'sound/items/PDA/ambicha4-short.ogg', - "xeno" = 'sound/voice/hiss1.ogg') 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. + var/latest_post = 0 + var/auto_scroll = 1 /datum/data/pda/app/messenger/start() . = ..() - set_new(0) + unnotify() + latest_post = 0 /datum/data/pda/app/messenger/update_ui(mob/user as mob, list/data) - data["silent"] = silent // does the pda make noise when it receives a message? + data["silent"] = notify_silent // does the pda make noise when it receives a message? data["toff"] = toff // is the messenger function turned off? data["active_conversation"] = active_conversation // Which conversation are we following right now? - var/convopdas[0] - var/pdas[0] - var/count = 0 - for(var/A in PDAs) - var/obj/item/device/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("\ref[P]")) - convopdas.Add(list(list("Name" = "[P]", "Reference" = "\ref[P]", "Detonate" = "[P.detonate]", "inconvo" = "1"))) - else - pdas.Add(list(list("Name" = "[P]", "Reference" = "\ref[P]", "Detonate" = "[P.detonate]", "inconvo" = "0"))) - count++ - - data["convopdas"] = convopdas - data["pdas"] = pdas - data["pda_count"] = count - - data["messagescount"] = tnote.len - data["messages"] = tnote - has_back = active_conversation if(active_conversation) + data["messages"] = tnote for(var/c in tnote) if(c["target"] == active_conversation) data["convo_name"] = sanitize(c["owner"]) data["convo_job"] = sanitize(c["job"]) break + data["auto_scroll"] = auto_scroll + data["latest_post"] = latest_post + latest_post = tnote.len + else + var/convopdas[0] + var/pdas[0] + for(var/A in PDAs) + var/obj/item/device/pda/P = A + var/datum/data/pda/app/messenger/PM = P.find_program(/datum/data/pda/app/messenger) - 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, ref = "\ref[P]")) - data["plugins"] = plugins + if (!P.owner || PM.toff || P == pda || PM.m_hidden) + continue + if(conversations.Find("\ref[P]")) + convopdas.Add(list(list("Name" = "[P]", "Reference" = "\ref[P]", "Detonate" = "[P.detonate]", "inconvo" = "1"))) + else + pdas.Add(list(list("Name" = "[P]", "Reference" = "\ref[P]", "Detonate" = "[P.detonate]", "inconvo" = "0"))) - if(pda.cartridge) - data["charges"] = pda.cartridge.charges ? pda.cartridge.charges : 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, ref = "\ref[P]")) + data["plugins"] = plugins + + if(pda.cartridge) + data["charges"] = pda.cartridge.charges ? pda.cartridge.charges : 0 /datum/data/pda/app/messenger/Topic(href, list/href_list) - set_new(0) + unnotify() switch(href_list["choice"]) if("Toggle Messenger") toff = !toff if("Toggle Ringer")//If viewing texts then erase them, if not then toggle silent status - silent = !silent + notify_silent = !notify_silent if("Clear")//Clears messages if(href_list["option"] == "All") tnote.Cut() @@ -90,29 +84,19 @@ conversations.Remove(active_conversation) active_conversation = null - if("Ringtone") - var/t = input("Please enter new ringtone", name, pda.ttone) as text - if (in_range(pda, usr) && pda.loc == usr) - if (t) - if(pda.hidden_uplink && pda.hidden_uplink.check_trigger(usr, lowertext(t), lowertext(pda.lock_code))) - usr << "The PDA softly beeps." - pda.close(usr) - else - t = sanitize(copytext(t, 1, 20)) - pda.ttone = t - else - pda.close(usr) - return 0 + latest_post = 0 if("Message") var/obj/item/device/pda/P = locate(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"] + latest_post = 0 if("Select Conversation") var/P = href_list["convo"] for(var/n in conversations) if(P == n) active_conversation = P + latest_post = 0 if("Messenger Plugin") if(!href_list["target"] || !href_list["plugin"]) return @@ -122,30 +106,14 @@ usr << "PDA not found." var/datum/data/pda/messenger_plugin/plugin = locate(href_list["plugin"]) - if(plugin && plugin in pda.cartridge.messenger_plugins) + if(plugin && (plugin in pda.cartridge.messenger_plugins)) plugin.messenger = src plugin.user_act(usr, P) if("Back") active_conversation = null - -/datum/data/pda/app/messenger/proc/set_new(isnew) - if(pda.newmessage == isnew) - return - - if(pda.newmessage) - //To clear message overlays. - pda.overlays.Cut() - pda.newmessage = 0 - - icon = "comments" - pda.update_shortcuts() - else - pda.overlays.Cut() - pda.overlays += image('icons/obj/pda.dmi', "pda-r") - pda.newmessage = 1 - - icon = "comments-o" - pda.update_shortcuts() + latest_post = 0 + if("Autoscroll") + auto_scroll = !auto_scroll /datum/data/pda/app/messenger/proc/create_message(var/mob/living/U, var/obj/item/device/pda/P) var/t = input(U, "Please enter message", name, null) as text|null @@ -207,39 +175,12 @@ if(!PM.conversations.Find("\ref[pda]")) PM.conversations.Add("\ref[pda]") - PM.play_ringtone() - //Search for holder of the PDA. - var/mob/living/L = null - if(P.loc && isliving(P.loc)) - L = P.loc - //Maybe they are a pAI! - else - L = get(P, /mob/living/silicon) - - - if(L) - L << "\icon[P] Message from [pda.owner] ([pda.ownjob]), \"[t]\" (Reply)" - nanomanager.update_user_uis(L, P) // Update the receiving user's PDA UI so that they can see the new message - nanomanager.update_user_uis(U, P) // Update the sending user's PDA UI so that they can see the new message - set_new(1) + PM.notify("Message from [pda.owner] ([pda.ownjob]), \"[t]\" (Reply)") log_pda("[usr] (PDA: [src.name]) sent \"[t]\" to [P.name]") else U << "ERROR: Messaging server is not responding." -/datum/data/pda/app/messenger/proc/play_ringtone() - if (!silent) - var/S - - if(pda.ttone in ttone_sound) - S = ttone_sound[pda.ttone] - else - S = 'sound/machines/twobeep.ogg' - playsound(pda.loc, S, 50, 1) - for(var/mob/O in hearers(3, pda.loc)) - if(!silent) - O.show_message(text("\icon[pda] *[pda.ttone]*")) - /datum/data/pda/app/messenger/proc/available_pdas() var/list/names = list() var/list/plist = list() diff --git a/code/modules/pda/messenger_plugins.dm b/code/modules/pda/messenger_plugins.dm index ed4d330fdba..98cab31aaf7 100644 --- a/code/modules/pda/messenger_plugins.dm +++ b/code/modules/pda/messenger_plugins.dm @@ -34,10 +34,13 @@ . = ..(user, P) if(.) user.show_message("Virus sent!", 1) - var/datum/data/pda/app/messenger/M = P.find_program(/datum/data/pda/app/messenger) + var/datum/data/pda/app/M = P.find_program(/datum/data/pda/app/messenger) if(M) - M.silent = 1 - P.ttone = "silence" + M.notify_silent = 1 + M = P.find_program(/datum/data/pda/app/chatroom) + if(M) + M.notify_silent = 1 + P.ttone = "silence" /datum/data/pda/messenger_plugin/virus/detonate diff --git a/code/modules/pda/pdas.dm b/code/modules/pda/pdas.dm index 1e15144c5fd..6ad7f2b378c 100644 --- a/code/modules/pda/pdas.dm +++ b/code/modules/pda/pdas.dm @@ -50,9 +50,12 @@ /obj/item/device/pda/mime/New() ..() - var/datum/data/pda/app/messenger/M = find_program(/datum/data/pda/app/messenger) + var/datum/data/pda/app/M = find_program(/datum/data/pda/app/messenger) if(M) - M.silent = 1 + M.notify_silent = 1 + M = find_program(/datum/data/pda/app/chatroom) + if(M) + M.notify_silent = 1 /obj/item/device/pda/heads default_cartridge = /obj/item/weapon/cartridge/head @@ -142,9 +145,12 @@ /obj/item/device/pda/librarian/New() ..() - var/datum/data/pda/app/messenger/M = find_program(/datum/data/pda/app/messenger) + var/datum/data/pda/app/M = find_program(/datum/data/pda/app/messenger) if(M) - M.silent = 1 //Quiet in the library! + M.notify_silent = 1 //Quiet in the library! + M = find_program(/datum/data/pda/app/chatroom) + if(M) + M.notify_silent = 1 //Quiet in the library! /obj/item/device/pda/clear icon_state = "pda-transp" diff --git a/nano/templates/pda.tmpl b/nano/templates/pda.tmpl index 3d11ee0a6f8..dfd691fedbd 100644 --- a/nano/templates/pda.tmpl +++ b/nano/templates/pda.tmpl @@ -27,6 +27,10 @@ Used In File(s): \code\game\objects\items\devices\PDA\PDA.dm color: #222222; } + .bad { + color: #333333; + } + .pdanote { color: #777777; } diff --git a/nano/templates/pda_chatroom.tmpl b/nano/templates/pda_chatroom.tmpl new file mode 100644 index 00000000000..6ba79a5e5ff --- /dev/null +++ b/nano/templates/pda_chatroom.tmpl @@ -0,0 +1,84 @@ + +
+
+ Chat Functions: +
+
+ {{:helper.link(data.silent==1 ? 'Ringer: Off' : 'Ringer: On', data.silent==1 ? 'volume-off' : 'volume-up', {'choice' : "Toggle Ringer"}, null, 'pdalink fixedLeftWide')}} + {{:helper.link(data.toff==1 ? 'Notifications: Off' : 'Notifications: On',data.toff==1 ? 'close' : 'check', {'choice' : "Toggle Chatroom"}, null, 'pdalink fixedLeftWide')}} + {{:helper.link('Set Ringtone', 'bell-o', {'choice' : "Ringtone"}, null, 'pdalink fixedLeftWide')}} + {{:helper.link('New Room', 'plus', {'choice' : "New Room"}, null, 'pdalink fixedLeftWide')}} +
+
+ +
+ {{if data.no_server}} +

ERROR: Messaging server is not responding.

+ {{else data.room}} + {{if data.inviting}} +

Invite whom to #{{:data.room}}?

+ {{for data.people}} + {{:helper.link(value.name, 'user-plus', {'choice': "Invite PDA", 'user': value.ref}, null, 'pdalink fixedLeftWidest')}} + {{empty}} + No other people found. + {{/for}} + {{else}} +

#{{:data.room}} – {{:data.topic}}

+
+
+ Room Functions: +
+
+ {{:helper.link('Invite', 'user-plus', {'choice' : "Invite"}, null, 'pdalink fixedLeftWide')}} + {{:helper.link('Change Topic', 'tag', {'choice' : "Topic"}, null, 'pdalink fixedLeftWide')}} + {{:helper.link('Leave Channel', 'user-times', {'choice' : "Leave"}, null, 'pdalink fixedLeftWide')}} + {{:helper.link(data.auto_scroll ? 'Autoscroll: On' : 'Autoscroll: Off', 'level-down', {'choice' : "Autoscroll"}, null, 'pdalink fixedLeftWide')}} +
+
+
+
+ {{var prevName = "";}} + {{for data.history}} +
+
{{:value.username!=prevName ? value.username : " "}}
+
+ {{:value.message}} +
+
+ {{prevName = value.username;}} + {{/for}} +
+
+ {{:helper.link('Post', 'comment', {'choice' : "Post"}, null, 'pdalink fixedLeftWidest')}} +
+
+
+ {{for data.users}} +
+
{{:value}}
+
+ {{/for}} +
+ + {{/if}} + {{else}} +

Rooms

+ {{for data.rooms}} +
+ {{:helper.link(value.name, 'arrow-circle-down', {'choice' : "Join", 'room' : value.ref}, null, 'pdalink fixedLeftWidest')}} +
+ {{empty}} + No rooms located. + {{/for}} + {{/if}} +
\ No newline at end of file diff --git a/nano/templates/pda_main_menu.tmpl b/nano/templates/pda_main_menu.tmpl index 680e4a8fa75..692cdb7039d 100644 --- a/nano/templates/pda_main_menu.tmpl +++ b/nano/templates/pda_main_menu.tmpl @@ -2,6 +2,25 @@ Title: PDA Home UI Used In File(s): \code\game\objects\items\devices\PDA\core_apps.dm --> + + +
Owner: @@ -29,7 +48,16 @@ Used In File(s): \code\game\objects\items\devices\PDA\core_apps.dm
{{for data.apps[cat]}} - {{:helper.link(value.name, value.icon, {'choice' : "StartProgram", 'program' : value.ref}, null, 'pdalink fixedLeftWide')}} + {{if value.ref in data.notifying}} +
+ {{:helper.link(value.name, value.notify_icon, {'choice' : "StartProgram", 'program' : value.ref}, null, 'pdalink fixedLeftWide')}} +
+ + {{else}} + {{:helper.link(value.name, value.icon, {'choice' : "StartProgram", 'program' : value.ref}, null, 'pdalink fixedLeftWide')}} + {{/if}} {{/for}}
diff --git a/nano/templates/pda_messenger.tmpl b/nano/templates/pda_messenger.tmpl index 633ae7d4691..4871934e4e9 100644 --- a/nano/templates/pda_messenger.tmpl +++ b/nano/templates/pda_messenger.tmpl @@ -9,6 +9,7 @@ Used In File(s): \code\game\objects\items\devices\PDA\core_apps.dm
{{:helper.link('Delete Conversation', 'trash', {'choice' : "Clear", 'option' : "Convo"}, null, 'pdalink fixedLeftWide')}} + {{:helper.link(data.auto_scroll ? 'Autoscroll: On' : 'Autoscroll: Off', 'level-down', {'choice' : "Autoscroll"}, null, 'pdalink fixedLeftWide')}}

@@ -29,7 +30,15 @@ Used In File(s): \code\game\objects\items\devices\PDA\core_apps.dm - {{:helper.link('Reply', 'comment', {'choice' : "Message", 'target': data.active_conversation}, null, 'pdalink fixedLeft')}} + {{:helper.link('Reply', 'comment', {'choice' : "Message", 'target': data.active_conversation}, null, 'pdalink fixedLeftWidest')}} + {{else}}
@@ -38,7 +47,7 @@ Used In File(s): \code\game\objects\items\devices\PDA\core_apps.dm
{{:helper.link(data.silent==1 ? 'Ringer: Off' : 'Ringer: On', data.silent==1 ? 'volume-off' : 'volume-up', {'choice' : "Toggle Ringer"}, null, 'pdalink fixedLeftWide')}} {{:helper.link(data.toff==1 ? 'Messenger: Off' : 'Messenger: On',data.toff==1 ? 'close':'check', {'choice' : "Toggle Messenger"}, null, 'pdalink fixedLeftWide')}} - {{:helper.link('Set Ringtone', 'comment', {'choice' : "Ringtone"}, null, 'pdalink fixedLeftWide')}} + {{:helper.link('Set Ringtone', 'bell-o', {'choice' : "Ringtone"}, null, 'pdalink fixedLeftWide')}} {{:helper.link('Delete all Conversations', 'trash', {'choice' : "Clear", 'option' : "All"}, null, 'pdalink fixedLeftWider')}}
@@ -51,7 +60,7 @@ Used In File(s): \code\game\objects\items\devices\PDA\core_apps.dm
{{/if}} - {{if data.pda_count == 0}} + {{if !data.convopdas.length && !data.pdas.length}} No other PDAS located {{else}}

Current Conversations