diff --git a/code/__DEFINES/pda.dm b/code/__DEFINES/pda.dm new file mode 100644 index 00000000000..d22b90870b0 --- /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 \ No newline at end of file diff --git a/code/_onclick/hud/ai.dm b/code/_onclick/hud/ai.dm index 790cbd305bc..0049537e9b4 100644 --- a/code/_onclick/hud/ai.dm +++ b/code/_onclick/hud/ai.dm @@ -100,7 +100,7 @@ /obj/screen/ai/pda_msg_send/Click() if(isAI(usr)) var/mob/living/silicon/ai/AI = usr - AI.cmd_send_pdamesg(usr) + AI.aiPDA.cmd_send_pdamesg() /obj/screen/ai/pda_msg_show name = "PDA - Show Message Log" @@ -109,7 +109,7 @@ /obj/screen/ai/pda_msg_show/Click() if(isAI(usr)) var/mob/living/silicon/ai/AI = usr - AI.cmd_show_message_log(usr) + AI.aiPDA.cmd_show_message_log() /obj/screen/ai/image_take name = "Take Image" diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 08e8f74b312..73ce77d0474 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -133,11 +133,11 @@ else msg += "However, we were unable to send you the $[pay] you're entitled." if(useMS && P) - // THIS SHOULD HAVE DONE EVERYTHING FOR ME useMS.send_pda_message("[P.owner]", "[command_name()] Payroll", msg) - // BUT NOPE, NEED TO DO THIS BULLSHIT. - P.play_ringtone() + 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)) diff --git a/code/game/gamemodes/mutiny/mutiny.dm b/code/game/gamemodes/mutiny/mutiny.dm index 1d2faebe5ff..113cffa46c0 100644 --- a/code/game/gamemodes/mutiny/mutiny.dm +++ b/code/game/gamemodes/mutiny/mutiny.dm @@ -105,7 +105,9 @@ datum/game_mode/mutiny if (!pda) return 0 - pda.play_ringtone() + 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() return 1 diff --git a/code/game/gamemodes/shadowling/shadowling_abilities.dm b/code/game/gamemodes/shadowling/shadowling_abilities.dm index f4186557627..2dfa31cc4a0 100644 --- a/code/game/gamemodes/shadowling/shadowling_abilities.dm +++ b/code/game/gamemodes/shadowling/shadowling_abilities.dm @@ -80,8 +80,9 @@ F.update_brightness() else if(istype(I, /obj/item/device/pda)) var/obj/item/device/pda/P = I - P.fon = 0 - P.set_light(0) + var/datum/data/pda/utility/flashlight/FL = P.find_program(/datum/data/pda/utility/flashlight) + if(FL && FL.fon) + FL.start() else if(istype(I, /obj/item/clothing/head/helmet/space/rig)) var/obj/item/clothing/head/helmet/space/rig/R = I if(R.on) diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index 5b1e1610e83..6e9c41ff983 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -205,8 +205,10 @@ info = X.info 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) + itemname = P.name + info = N.notehtml U << "You hold \the [itemname] up to the camera ..." U.changeNext_move(CLICK_CD_MELEE) for(var/mob/O in player_list) diff --git a/code/game/machinery/computer/message.dm b/code/game/machinery/computer/message.dm index 0ebb13efcd6..72d01fda958 100644 --- a/code/game/machinery/computer/message.dm +++ b/code/game/machinery/computer/message.dm @@ -408,7 +408,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) continue + var/datum/data/pda/app/messenger/PM = P.find_program(/datum/data/pda/app/messenger) + + if(!PM || !PM.can_receive()) + continue sendPDAs += P if(PDAs && PDAs.len > 0) customrecepient = input(usr, "Select a PDA from the list.") as null|anything in sortAtom(sendPDAs) @@ -426,7 +429,6 @@ //Send message if("Send") - if(isnull(customsender) || customsender == "") customsender = "UNKNOWN" @@ -438,36 +440,44 @@ message = "NOTICE: No message entered!" return src.attack_hand(usr) + var/datum/data/pda/app/messenger/recipient_messenger = customrecepient.find_program(/datum/data/pda/app/messenger) + + if(!recipient_messenger) + message = "ERROR: Message could not be transmitted!" + return src.attack_hand(usr) + var/obj/item/device/pda/PDARec = null for (var/obj/item/device/pda/P in PDAs) - if (!P.owner || P.toff || P.hidden) continue + var/datum/data/pda/app/messenger/PM = P.find_program(/datum/data/pda/app/messenger) + + if (!PM || !PM.can_receive()) + continue if(P.owner == customsender) PDARec = P + break //Sender isn't faking as someone who exists if(isnull(PDARec)) src.linkedServer.send_pda_message("[customrecepient.owner]", "[customsender]","[custommessage]") - customrecepient.play_ringtone() + 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)" log_pda("[usr] (PDA: [customsender]) sent \"[custommessage]\" to [customrecepient.owner]") - customrecepient.overlays.Cut() - customrecepient.overlays += image('icons/obj/pda.dmi', "pda-r") + recipient_messenger.set_new(1) //Sender is faking as someone who exists else src.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]"))) + recipient_messenger.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]") + if(!recipient_messenger.conversations.Find("\ref[PDARec]")) + recipient_messenger.conversations.Add("\ref[PDARec]") - customrecepient.play_ringtone() + 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)" log_pda("[usr] (PDA: [PDARec.owner]) sent \"[custommessage]\" to [customrecepient.owner]") - customrecepient.overlays.Cut() - customrecepient.overlays += image('icons/obj/pda.dmi', "pda-r") + recipient_messenger.set_new(1) //Finally.. ResetMessage() diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index 0939b189eb1..5f3d8698a11 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -836,11 +836,11 @@ icon_deny = "cart-deny" products = list(/obj/item/device/pda =10,/obj/item/weapon/cartridge/medical = 10,/obj/item/weapon/cartridge/chemistry = 10, /obj/item/weapon/cartridge/engineering = 10,/obj/item/weapon/cartridge/atmos = 10,/obj/item/weapon/cartridge/janitor = 10, - /obj/item/weapon/cartridge/signal/toxins = 10,/obj/item/weapon/cartridge/signal = 10,/obj/item/weapon/cartridge = 10) + /obj/item/weapon/cartridge/signal/toxins = 10,/obj/item/weapon/cartridge/signal = 10) contraband = list(/obj/item/weapon/cartridge/clown = 1,/obj/item/weapon/cartridge/mime = 1) prices = list(/obj/item/device/pda =300,/obj/item/weapon/cartridge/medical = 200,/obj/item/weapon/cartridge/chemistry = 150,/obj/item/weapon/cartridge/engineering = 100, /obj/item/weapon/cartridge/atmos = 75,/obj/item/weapon/cartridge/janitor = 100,/obj/item/weapon/cartridge/signal/toxins = 150, - /obj/item/weapon/cartridge/signal = 75,/obj/item/weapon/cartridge = 50) + /obj/item/weapon/cartridge/signal = 75) /obj/machinery/vending/liberationstation diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index 697e2c9e867..d824b1b0a10 100755 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -17,45 +17,31 @@ var/global/list/obj/item/device/pda/PDAs = list() 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/datum/data/pda/app/current_app = null + var/datum/data/pda/app/lastapp = null var/ui_tick = 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/silent = 0 //To beep or not to beep, that is the question - 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 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/model_name = "Thinktronic 5230 Personal Data Assistant" + var/datum/data/pda/utility/scanmode/scanmode = null 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/newmessage = 0 //To remove hackish overlay check + var/ttone = "beep" //The ringtone! - 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/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/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/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 @@ -64,271 +50,6 @@ var/global/list/obj/item/device/pda/PDAs = list() var/obj/item/device/paicard/pai = null // A slot for a personal AI device var/retro_mode = 0 -/obj/item/device/pda/medical - default_cartridge = /obj/item/weapon/cartridge/medical - icon_state = "pda-medical" - -/obj/item/device/pda/viro - default_cartridge = /obj/item/weapon/cartridge/medical - icon_state = "pda-virology" - -/obj/item/device/pda/engineering - default_cartridge = /obj/item/weapon/cartridge/engineering - icon_state = "pda-engineer" - -/obj/item/device/pda/security - default_cartridge = /obj/item/weapon/cartridge/security - icon_state = "pda-security" - -/obj/item/device/pda/detective - default_cartridge = /obj/item/weapon/cartridge/detective - icon_state = "pda-security" - -/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-janitor" - ttone = "slip" - -/obj/item/device/pda/toxins - default_cartridge = /obj/item/weapon/cartridge/signal/toxins - icon_state = "pda-science" - 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" - silent = 1 - ttone = "silence" - -/obj/item/device/pda/heads - default_cartridge = /obj/item/weapon/cartridge/head - icon_state = "pda-h" - -/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-captain" - detonate = 0 - //toff = 1 - -/obj/item/device/pda/heads/ntrep - default_cartridge = /obj/item/weapon/cartridge/supervisor - icon_state = "pda-h" - -/obj/item/device/pda/heads/magistrate - default_cartridge = /obj/item/weapon/cartridge/supervisor - icon_state = "pda-h" - -/obj/item/device/pda/heads/blueshield - default_cartridge = /obj/item/weapon/cartridge/hos - icon_state = "pda-h" - -/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-qm" - -/obj/item/device/pda/shaftminer - icon_state = "pda-miner" - -/obj/item/device/pda/syndicate - default_cartridge = /obj/item/weapon/cartridge/syndicate - icon_state = "pda-syndi" - name = "Military PDA" - owner = "John Doe" - hidden = 1 - -/obj/item/device/pda/chaplain - icon_state = "pda-chaplain" - 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/botanist - icon_state = "pda-hydro" - -/obj/item/device/pda/roboticist - icon_state = "pda-roboticist" - -/obj/item/device/pda/librarian - icon_state = "pda-library" - 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!" - silent = 1 //Quiet in the library! - -/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 - icon_state = "pda-chef" - -/obj/item/device/pda/bar - icon_state = "pda-bartender" - -/obj/item/device/pda/atmos - default_cartridge = /obj/item/weapon/cartridge/atmos - icon_state = "pda-atmos" - -/obj/item/device/pda/chemist - default_cartridge = /obj/item/weapon/cartridge/chemistry - icon_state = "pda-chemistry" - -/obj/item/device/pda/geneticist - default_cartridge = /obj/item/weapon/cartridge/medical - icon_state = "pda-genetics" - -/obj/item/device/pda/centcom - default_cartridge = /obj/item/weapon/cartridge/centcom - icon_state = "pda-h" - - -// Special AI/pAI PDAs that cannot explode. -/obj/item/device/pda/ai - icon_state = "NONE" - ttone = "data" - 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. -/mob/living/silicon/ai/proc/cmd_send_pdamesg(mob/user as mob) - if(user.stat == 2) - user << "You can't send PDA messages because you are dead!" - return - var/list/plist = aiPDA.available_pdas() - if (plist) - var/c = input(user, "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] - aiPDA.create_message(user, selected) - -/mob/living/silicon/ai/proc/cmd_show_message_log(mob/user as mob) - if(user.stat == 2) - user << "You can't do that because you are dead!" - return - var/HTML = "AI PDA Message Log" - for(var/index in aiPDA.tnote) - if(index["sent"]) - HTML += addtext("→ To ", index["owner"],":
", index["message"], "
") - else - HTML += addtext("← From ", index["owner"],":
", index["message"], "
") - HTML +="" - user << browse(HTML, "window=log;size=400x444;border=1;can_resize=1;can_close=1;can_minimize=0") - -/obj/item/device/pda/ai/verb/cmd_send_pdamesg() - set category = "AI IM" - set name = "Send PDA Message" - set src in usr - if(usr.stat == 2) - 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) - -/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) - usr << "You can't do that because you are dead!" - return - var/HTML = "AI PDA Message Log" - for(var/index in tnote) - if(index["sent"]) - HTML += addtext("→ To ", index["owner"],":
", index["message"], "
") - else - HTML += addtext("← From ", index["owner"],":
", index["message"], "
") - HTML +="" - usr << browse(HTML, "window=log;size=400x444;border=1;can_resize=1;can_close=1;can_minimize=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) - usr << "You can't do that because you are dead!" - return - toff = !toff - 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) - usr << "You can't do that because you are dead!" - return - silent=!silent - usr << "PDA ringer toggled [(silent ? "Off" : "On")]!" - -/obj/item/device/pda/ai/can_use() - return 1 - - -/obj/item/device/pda/ai/attack_self(mob/user as mob) - if ((honkamt > 0) && (prob(60)))//For clown virus. - honkamt-- - playsound(loc, 'sound/items/bikehorn.ogg', 30, 1) - return - - -/obj/item/device/pda/ai/pai - ttone = "assist" - /* * The Actual PDA @@ -337,12 +58,14 @@ var/global/list/obj/item/device/pda/PDAs = list() ..() PDAs += src PDAs = sortAtom(PDAs) + update_programs() if(default_cartridge) cartridge = new default_cartridge(src) + cartridge.update_programs(src) new /obj/item/weapon/pen(src) + start_program(find_program(/datum/data/pda/app/main_menu)) /obj/item/device/pda/proc/can_use() - if(!ismob(loc)) return 0 @@ -367,19 +90,20 @@ var/global/list/obj/item/device/pda/PDAs = list() var/mob/M = usr if((!istype(over_object, /obj/screen)) && can_use()) return attack_self(M) - return - /obj/item/device/pda/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) ui_tick++ var/datum/nanoui/old_ui = nanomanager.get_open_ui(user, src, "main") var/auto_update = 1 - if(mode in no_auto_update) - auto_update = 0 - if(old_ui && (mode == lastmode && ui_tick % 5 && mode in update_every_five)) + if(!current_app) return - lastmode = mode + if(current_app.update == PDA_APP_NOUPDATE && current_app == lastapp) + auto_update = 0 + if(old_ui && (current_app == lastapp && ui_tick % 5 && current_app.update == PDA_APP_UPDATE_SLOW)) + return + + lastapp = current_app var/title = "Personal Data Assistant" @@ -389,125 +113,46 @@ var/global/list/obj/item/device/pda/PDAs = list() data["owner"] = owner // Who is your daddy... data["ownjob"] = ownjob // ...and what does he do? - data["mode"] = mode // The current view - data["scanmode"] = scanmode // Scanners - data["fon"] = fon // Flashlight on? - data["pai"] = (isnull(pai) ? 0 : 1) // pAI inserted? - data["note"] = note // current pda notes - data["silent"] = 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? + // update list of shortcuts, only if they changed + if(!shortcut_cache.len) + shortcut_cache = list() + shortcut_cat_order = list() + var/prog_list = programs.Copy() + if(cartridge) + prog_list |= cartridge.programs + for(var/datum/data/pda/P in prog_list) + if(P.hidden) + continue + var/list/cat + if(P.category in shortcut_cache) + cat = shortcut_cache[P.category] + else + cat = list() + shortcut_cache[P.category] = cat + shortcut_cat_order += P.category + cat |= list(list(name = P.name, icon = P.icon, ref = "\ref[P]")) + + // force the order of a few core categories + shortcut_cat_order = list("General") \ + + sortList(shortcut_cat_order - list("General", "Scanners", "Utilities")) \ + + list("Scanners", "Utilities") data["idInserted"] = (id ? 1 : 0) data["idLink"] = (id ? text("[id.registered_name], [id.assignment]") : "--------") data["useRetro"] = retro_mode - data["cart_loaded"] = cartridge ? 1:0 - if(cartridge) - var/cartdata[0] - - cartdata["access"] = list(\ - "access_security" = cartridge.access_security,\ - "access_engine" = cartridge.access_engine,\ - "access_atmos" = cartridge.access_atmos,\ - "access_medical" = cartridge.access_medical,\ - "access_clown" = cartridge.access_clown,\ - "access_mime" = cartridge.access_mime,\ - "access_janitor" = cartridge.access_janitor,\ - "access_quartermaster" = cartridge.access_quartermaster,\ - "access_hydroponics" = cartridge.access_hydroponics,\ - "access_reagent_scanner" = cartridge.access_reagent_scanner,\ - "access_remote_door" = cartridge.access_remote_door,\ - "access_status_display" = cartridge.access_status_display,\ - "access_detonate_pda" = cartridge.access_detonate_pda\ - ) - - if(mode in cartmodes) - data["records"] = cartridge.create_NanoUI_values() - - if(mode == 0) - cartdata["name"] = cartridge.name - if(isnull(cartridge.radio)) - cartdata["radio"] = 0 - else - if(istype(cartridge.radio, /obj/item/radio/integrated/beepsky)) - cartdata["radio"] = 1 - if(istype(cartridge.radio, /obj/item/radio/integrated/signal)) - cartdata["radio"] = 2 - if(istype(cartridge.radio, /obj/item/radio/integrated/mule)) - cartdata["radio"] = 3 - - if(mode == 2) - cartdata["charges"] = cartridge.charges ? cartridge.charges : 0 - data["cartridge"] = cartdata + data["cartridge_name"] = cartridge ? cartridge.name : "" data["stationTime"] = worldtime2text() - data["newMessage"] = newmessage - if(mode==2) - var/convopdas[0] - var/pdas[0] - var/count = 0 - for (var/obj/item/device/pda/P in PDAs) - if (!P.owner||P.toff||P == src||P.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 - - if(mode==21) - data["messagescount"] = tnote.len - data["messages"] = tnote - else - data["messagescount"] = null - data["messages"] = null - - if(active_conversation) - for(var/c in tnote) - if(c["target"] == active_conversation) - data["convo_name"] = sanitize(c["owner"]) - data["convo_job"] = sanitize(c["job"]) - break - if(mode==41) - data_core.get_manifest_json() - - - if(mode==3) - var/turf/T = get_turf(user.loc) - if(!isnull(T)) - var/datum/gas_mixture/environment = T.return_air() - - var/pressure = environment.return_pressure() - var/total_moles = environment.total_moles() - - if (total_moles) - var/o2_level = environment.oxygen/total_moles - var/n2_level = environment.nitrogen/total_moles - var/co2_level = environment.carbon_dioxide/total_moles - var/plasma_level = environment.toxins/total_moles - var/unknown_level = 1-(o2_level+n2_level+co2_level+plasma_level) - data["aircontents"] = list(\ - "pressure" = "[round(pressure,0.1)]",\ - "nitrogen" = "[round(n2_level*100,0.1)]",\ - "oxygen" = "[round(o2_level*100,0.1)]",\ - "carbon_dioxide" = "[round(co2_level*100,0.1)]",\ - "plasma" = "[round(plasma_level*100,0.01)]",\ - "other" = "[round(unknown_level, 0.01)]",\ - "temp" = "[round(environment.temperature-T0C,0.1)]",\ - "reading" = 1\ - ) - if(isnull(data["aircontents"])) - - data["aircontents"] = list("reading" = 0) - - - data["manifest"] = list("__json_cache" = ManifestJSON) + data["app"] = list() + current_app.update_ui(user, data) + data["app"] |= list( + "name" = current_app.title, + "icon" = current_app.icon, + "template" = current_app.template, + "has_back" = current_app.has_back) // update the ui if it exists, returns null if no ui is passed/found ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) @@ -515,37 +160,53 @@ var/global/list/obj/item/device/pda/PDAs = list() // the ui does not exist, so we'll create a new() one // for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm ui = new(user, src, ui_key, "pda.tmpl", title, 630, 600, state = inventory_state) + ui.set_state_key("pda") // when the ui is first opened this is the data it will use ui.set_initial_data(data) // open the new ui window ui.open() + // auto update every Master Controller tick ui.set_auto_update(auto_update) -//NOTE: graphic resources are loaded on client login /obj/item/device/pda/attack_self(mob/user as mob) user.set_machine(src) if(active_uplink_check(user)) return ui_interact(user) //NanoUI requires this proc - return + +/obj/item/device/pda/proc/start_program(datum/data/pda/P) + if(P && ((P in programs) || (cartridge && (P in cartridge.programs)))) + return P.start() + return 0 + +/obj/item/device/pda/proc/find_program(type) + var/datum/data/pda/A = locate(type) in programs + if(A) + return A + if(cartridge) + A = locate(type) in cartridge.programs + if(A) + return A + return null + +// force the cache to rebuild on update_ui +/obj/item/device/pda/proc/update_shortcuts() + shortcut_cache.Cut() + +/obj/item/device/pda/proc/update_programs() + for(var/datum/data/pda/P in programs) + P.pda = src /obj/item/device/pda/Topic(href, href_list) - if(href_list["cartmenu"] && !isnull(cartridge)) - cartridge.Topic(href, href_list) - return 1 - if(href_list["radiomenu"] && !isnull(cartridge) && !isnull(cartridge.radio)) - cartridge.radio.Topic(href, href_list) - return 1 + . = ..() + if(.) + return - - ..() var/mob/user = usr var/datum/nanoui/ui = nanomanager.get_open_ui(user, src, "main") var/mob/living/U = usr - //Looking for master was kind of pointless since PDAs don't appear to have one. - //if ((src in U.contents) || ( istype(loc, /turf) && in_range(src, U) ) ) if (usr.stat == DEAD) return 0 if(!can_use()) //Why reinvent the wheel? There's a proc that does exactly that. @@ -557,270 +218,55 @@ var/global/list/obj/item/device/pda/PDAs = list() add_fingerprint(U) U.set_machine(src) + if(href_list["radiomenu"] && !isnull(cartridge) && !isnull(cartridge.radio)) + cartridge.radio.Topic(href, href_list) + return 1 + + . = 1 + switch(href_list["choice"]) - -//BASIC FUNCTIONS=================================== - - if("Close")//Self explanatory - U.unset_machine() - ui.close() - return 0 - if("Refresh")//Refresh, goes to the end of the proc. - if("Return")//Return - if(mode<=9) - mode = 0 - else - mode = round(mode/10) - if(mode==2) - active_conversation = null - if(mode==4)//Fix for cartridges. Redirects to hub. - mode = 0 - else if(mode >= 40 && mode <= 49)//Fix for cartridges. Redirects to refresh the menu. - cartridge.mode = mode - if("Retro") - retro_mode = !retro_mode - ui_interact(user) - if ("Authenticate")//Checks for ID - id_check(U, 1) - if("UpdateInfo") - ownjob = id.assignment - ownrank = id.rank - name = "PDA-[owner] ([ownjob])" + if("Home")//Go home, largely replaces the old Return + var/datum/data/pda/app/main_menu/A = find_program(/datum/data/pda/app/main_menu) + if(A) + start_program(A) + if("StartProgram") + if(href_list["program"]) + var/datum/data/pda/app/A = locate(href_list["program"]) + if(A) + start_program(A) if("Eject")//Ejects the cart, only done from hub. if (!isnull(cartridge)) var/turf/T = loc if(ismob(T)) T = T.loc - cartridge.loc = T - mode = 0 - scanmode = 0 - if (cartridge.radio) - cartridge.radio.hostpda = null + var/obj/item/weapon/cartridge/C = cartridge + C.loc = T + if(scanmode in C.programs) + scanmode = null + if(current_app in C.programs) + start_program(find_program(/datum/data/pda/app/main_menu)) + if(C.radio) + C.radio.hostpda = null cartridge = null - -//MENU FUNCTIONS=================================== - - if("0")//Hub - mode = 0 - if("1")//Notes - mode = 1 - if("2")//Messenger - mode = 2 - if("21")//Read messages - mode = 21 - if("3")//Atmos scan - mode = 3 - if("4")//Redirects to hub - mode = 0 - if("chatroom") // chatroom hub - mode = 5 - if("41") //Manifest - mode = 41 - - -//MAIN FUNCTIONS=================================== - - if("Light") - if(fon) - fon = 0 - set_light(0) - else - fon = 1 - set_light(f_lum) - if("Medical Scan") - if(scanmode == 1) - scanmode = 0 - else if((!isnull(cartridge)) && (cartridge.access_medical)) - scanmode = 1 - if("Reagent Scan") - if(scanmode == 3) - scanmode = 0 - else if((!isnull(cartridge)) && (cartridge.access_reagent_scanner)) - scanmode = 3 - if("Halogen Counter") - if(scanmode == 4) - scanmode = 0 - else if((!isnull(cartridge)) && (cartridge.access_engine)) - scanmode = 4 - if("Honk") - if ( !(last_honk && world.time < last_honk + 20) ) - playsound(loc, 'sound/items/bikehorn.ogg', 50, 1) - last_honk = world.time - if("Gas Scan") - if(scanmode == 5) - scanmode = 0 - else if((!isnull(cartridge)) && (cartridge.access_atmos)) - scanmode = 5 - -//MESSENGER/NOTE FUNCTIONS=================================== - - if ("Edit") - var/n = input(U, "Please enter message", name, notehtml) as message - if (in_range(src, U) && loc == U) - n = copytext(adminscrub(n), 1, MAX_MESSAGE_LEN) - if (mode == 1) - note = html_decode(n) - notehtml = note - note = replacetext(note, "\n", "
") - else - ui.close() - 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 - if(href_list["option"] == "All") - tnote.Cut() - conversations.Cut() - if(href_list["option"] == "Convo") - var/new_tnote[0] - 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(mode==21) - mode=2 - - if("Ringtone") - var/t = input(U, "Please enter new ringtone", name, ttone) as text - if (in_range(src, U) && loc == U) - if (t) - if(src.hidden_uplink && hidden_uplink.check_trigger(U, lowertext(t), lowertext(lock_code))) - U << "The PDA softly beeps." - ui.close() - else - t = sanitize(copytext(t, 1, 20)) - ttone = t - else - ui.close() - return 0 - if("Message") - - var/obj/item/device/pda/P = locate(href_list["target"]) - src.create_message(U, P) - if(mode == 2) - if(href_list["target"] in conversations) // Need to make sure the message went through, if not welp. - active_conversation = href_list["target"] - mode = 21 - - if("Select Conversation") - var/P = href_list["convo"] - for(var/n in conversations) - if(P == n) - active_conversation=P - mode=21 - if("Send Honk")//Honk virus - if(istype(cartridge, /obj/item/weapon/cartridge/clown))//Cartridge checks are kind of unnecessary since everything is done through switch. - var/obj/item/device/pda/P = locate(href_list["target"])//Leaving it alone in case it may do something useful, I guess. - if(!isnull(P)) - if (!P.toff && cartridge.charges > 0) - cartridge.charges-- - U.show_message("\blue Virus sent!", 1) - P.honkamt = (rand(15,20)) - else - U << "PDA not found." - else - ui.close() - return 0 - if("Send Silence")//Silent virus - if(istype(cartridge, /obj/item/weapon/cartridge/mime)) - var/obj/item/device/pda/P = locate(href_list["target"]) - if(!isnull(P)) - if (!P.toff && cartridge.charges > 0) - cartridge.charges-- - U.show_message("\blue Virus sent!", 1) - P.silent = 1 - P.ttone = "silence" - else - U << "PDA not found." - else - ui.close() - return 0 - - -//SYNDICATE FUNCTIONS=================================== - - if("Toggle Door") - if(cartridge && cartridge.access_remote_door) - for(var/obj/machinery/door/poddoor/M in world) - if(M.id_tag == cartridge.remote_door_id) - if(M.density) - M.open() - else - M.close() - - if("Detonate")//Detonate PDA - if(istype(cartridge, /obj/item/weapon/cartridge/syndicate)) - var/obj/item/device/pda/P = locate(href_list["target"]) - if(!isnull(P)) - if (!P.toff && cartridge.charges > 0) - cartridge.charges-- - - var/difficulty = 0 - - if(P.cartridge) - difficulty += P.cartridge.access_medical - difficulty += P.cartridge.access_security - difficulty += P.cartridge.access_engine - difficulty += P.cartridge.access_clown - difficulty += P.cartridge.access_janitor - else - difficulty += 2 - - if(prob(difficulty * 12) || (P.hidden_uplink)) - U.show_message("\red An error flashes on your [src].", 1) - else if (prob(difficulty * 3)) - U.show_message("\red Energy feeds back into your [src]!", 1) - ui.close() - explode() - log_admin("[key_name(U)] just attempted to blow up [P] with the Detomatix cartridge but failed, blowing themselves up") - message_admins("[key_name_admin(U)] just attempted to blow up [P] with the Detomatix cartridge but failed, blowing themselves up", 1) - else - U.show_message("\blue Success!", 1) - log_admin("[key_name(U)] just attempted to blow up [P] with the Detomatix cartridge and succeded") - message_admins("[key_name_admin(U)] just attempted to blow up [P] with the Detomatix cartridge and succeded", 1) - P.explode() - else - U << "PDA not found." - else - U.unset_machine() - ui.close() - return 0 - -//pAI FUNCTIONS=================================== - if("pai") - if(pai) - if(pai.loc != src) - pai = null - else - switch(href_list["option"]) - if("1") // Configure pAI device - pai.attack_self(U) - if("2") // Eject pAI device - var/turf/T = get_turf_or_move(src.loc) - if(T) - pai.loc = T - pai = null - + update_shortcuts() + if ("Authenticate")//Checks for ID + id_check(usr, 1) + if("Retro") + retro_mode = !retro_mode else - mode = text2num(href_list["choice"]) - if(cartridge) - cartridge.mode = mode + if(current_app) + . = current_app.Topic(href, href_list) //EXTRA FUNCTIONS=================================== - - if (mode == 2||mode == 21)//To clear message overlays. - overlays.Cut() - newmessage = 0 - if ((honkamt > 0) && (prob(60)))//For clown virus. honkamt-- playsound(loc, 'sound/items/bikehorn.ogg', 30, 1) - return 1 // return 1 tells it to refresh the UI in NanoUI + return // return 1 tells it to refresh the UI in NanoUI + +/obj/item/device/pda/proc/close(mob/user) + var/datum/nanoui/ui = nanomanager.get_open_ui(user, src, "main") + ui.close() /obj/item/device/pda/verb/verb_reset_pda() set category = "Object" @@ -831,8 +277,7 @@ var/global/list/obj/item/device/pda/PDAs = list() return if(can_use(usr)) - mode = 0 - nanomanager.update_uis(src) + start_program(find_program(/datum/data/pda/app/main_menu)) usr << "You press the reset button on \the [src]." else usr << "You cannot do this while restrained." @@ -847,113 +292,6 @@ var/global/list/obj/item/device/pda/PDAs = list() id.loc = get_turf(src) id = null -/obj/item/device/pda/proc/create_message(var/mob/living/U = usr, var/obj/item/device/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)) - t = readd_quotes(t) - if (!t || !istype(P)) - return - if (!in_range(src, U) && loc != U) - return - - if (isnull(P)||P.toff || toff) - return - - if (last_text && world.time < last_text + 5) - return - - if(!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(message_servers) - for (var/obj/machinery/message_server/MS in message_servers) - //PDAs are now dependent on the Message Server. - if(MS.active) - useMS = MS - break - - var/datum/signal/signal = src.telecomms_process() - - var/useTC = 0 - if(signal) - if(signal.data["done"]) - useTC = 1 - var/turf/pos = get_turf(P) - if(pos.z in signal.data["level"]) - useTC = 2 - //Let's make this barely readable - if(signal.data["compression"] > 0) - t = Gibberish(t, signal.data["compression"] + 50) - - if(useMS && useTC) // only send the message if it's stable - if(useTC != 2) // Does our recipient have a broadcaster on their level? - U << "ERROR: Cannot reach recipient." - return - useMS.send_pda_message("[P.owner]","[owner]","[t]") - tnote.Add(list(list("sent" = 1, "owner" = "[P.owner]", "job" = "[P.ownjob]", "message" = "[t]", "target" = "\ref[P]"))) - P.tnote.Add(list(list("sent" = 0, "owner" = "[owner]", "job" = "[ownjob]", "message" = "[t]", "target" = "\ref[src]"))) -/* for(var/mob/M in player_list) - if(M.stat == DEAD && M.client && (M.client.prefs.toggles & CHAT_GHOSTEARS)) // src.client is so that ghosts don't have to listen to mice - if(istype(M, /mob/new_player)) - continue - M.show_message("PDA Message - [owner] -> [P.owner]: [t]") */ - investigate_log("PDA Message - [U.key] - [owner] -> [P.owner]: [t]", "pda") - if(!conversations.Find("\ref[P]")) - conversations.Add("\ref[P]") - if(!P.conversations.Find("\ref[src]")) - P.conversations.Add("\ref[src]") - -/* - if (prob(15)) //Give the AI a chance of intercepting the message - var/who = src.owner - if(prob(50)) - who = P.owner - for(var/mob/living/silicon/ai/ai in mob_list) - // Allows other AIs to intercept the message but the AI won't intercept their own message. - if(ai.aiPDA != P && ai.aiPDA != src) - ai.show_message("Intercepted message from [who]: [t]") -*/ - - P.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 [src.owner] ([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 - - log_pda("[usr] (PDA: [src.name]) sent \"[t]\" to [P.name]") - P.overlays.Cut() - P.overlays += image('icons/obj/pda.dmi', "pda-r") - P.newmessage = 1 - else - U << "ERROR: Messaging server is not responding." - -/obj/item/device/pda/proc/play_ringtone() - if (!silent) - var/sound/S = sound('sound/machines/twobeep.ogg') - - if(ttone in ttone_sound) - S = ttone_sound[ttone] - playsound(loc, S, 50, 1) - for (var/mob/O in hearers(3, loc)) - if(!silent) O.show_message(text("\icon[src] *[ttone]*")) - /obj/item/device/pda/verb/verb_remove_id() set category = "Object" set name = "Remove id" @@ -1015,15 +353,15 @@ var/global/list/obj/item/device/pda/PDAs = list() user.put_in_hands(old_id) return -// access to status display signals /obj/item/device/pda/attackby(obj/item/C as obj, mob/user as mob, params) ..() if(istype(C, /obj/item/weapon/cartridge) && !cartridge) cartridge = C user.drop_item() cartridge.loc = src + cartridge.update_programs(src) + update_shortcuts() user << "You insert [cartridge] into [src]." - nanomanager.update_uis(src) // update all UIs attached to src if(cartridge.radio) cartridge.radio.hostpda = src @@ -1044,15 +382,11 @@ var/global/list/obj/item/device/pda/PDAs = list() if( can_use(user) )//If they can still act. id_check(user, 2) user << "You put the ID into \the [src]'s slot." - 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/device/paicard) && !src.pai) user.drop_item() C.loc = src pai = C user << "You slot \the [C] into [src]." - nanomanager.update_uis(src) // update all UIs attached to src else if(istype(C, /obj/item/weapon/pen)) var/obj/item/weapon/pen/O = locate() in src if(O) @@ -1061,133 +395,14 @@ var/global/list/obj/item/device/pda/PDAs = list() user.drop_item() C.loc = src user << "You slide \the [C] into \the [src]." - return /obj/item/device/pda/attack(mob/living/C as mob, mob/living/user as mob) - if (istype(C, /mob/living/carbon)) - switch(scanmode) - if(1) - for (var/mob/O in viewers(C, null)) - O.show_message("\red [user] has analyzed [C]'s vitals!", 1) - - user.show_message("\blue Analyzing Results for [C]:") - user.show_message("\blue \t Overall Status: [C.stat > 1 ? "dead" : "[C.health - C.halloss]% healthy"]", 1) - user.show_message("\blue \t Damage Specifics: [C.getOxyLoss() > 50 ? "\red" : "\blue"][C.getOxyLoss()]-[C.getToxLoss() > 50 ? "\red" : "\blue"][C.getToxLoss()]-[C.getFireLoss() > 50 ? "\red" : "\blue"][C.getFireLoss()]-[C.getBruteLoss() > 50 ? "\red" : "\blue"][C.getBruteLoss()]", 1) - user.show_message("\blue \t Key: Suffocation/Toxin/Burns/Brute", 1) - user.show_message("\blue \t Body Temperature: [C.bodytemperature-T0C]°C ([C.bodytemperature*1.8-459.67]°F)", 1) - if(C.timeofdeath && (C.stat == DEAD || (C.status_flags & FAKEDEATH))) - user.show_message("\blue \t Time of Death: [C.timeofdeath]") - if(istype(C, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = C - var/list/damaged = H.get_damaged_organs(1,1) - user.show_message("\blue Localized Damage, Brute/Burn:",1) - if(length(damaged)>0) - for(var/obj/item/organ/external/org in damaged) - user.show_message(text("\blue \t []: []\blue-[]",capitalize(org.name),(org.brute_dam > 0)?"\red [org.brute_dam]":0,(org.burn_dam > 0)?"\red [org.burn_dam]":0),1) - else - user.show_message("\blue \t Limbs are OK.",1) - - if(2) - if (!istype(C:dna, /datum/dna)) - user << "\blue No fingerprints found on [C]" - else - user << text("\blue [C]'s Fingerprints: [md5(C:dna.uni_identity)]") - if ( !(C:blood_DNA) ) - user << "\blue No blood found on [C]" - if(C:blood_DNA) - qdel(C:blood_DNA) - else - user << "\blue Blood found on [C]. Analysing..." - spawn(15) - for(var/blood in C:blood_DNA) - user << "\blue Blood type: [C:blood_DNA[blood]]\nDNA: [blood]" - - if(4) - for (var/mob/O in viewers(C, null)) - O.show_message("\red [user] has analyzed [C]'s radiation levels!", 1) - - user.show_message("\blue Analyzing Results for [C]:") - if(C.radiation) - user.show_message("\green Radiation Level: \black [C.radiation]") - else - user.show_message("\blue No radiation detected.") + if (istype(C, /mob/living/carbon) && scanmode) + scanmode.scan_mob(C, user) /obj/item/device/pda/afterattack(atom/A as mob|obj|turf|area, mob/user as mob, proximity) - if(!proximity) return - switch(scanmode) - - if(3) - if(!isnull(A.reagents)) - if(A.reagents.reagent_list.len > 0) - var/reagents_length = A.reagents.reagent_list.len - user << "[reagents_length] chemical agent[reagents_length > 1 ? "s" : ""] found." - for (var/re in A.reagents.reagent_list) - user << "\t [re]" - else - user << "No active chemical agents found in [A]." - else - user << "No significant chemical agents found in [A]." - - if(5) - if (istype(A, /obj/item/weapon/tank)) - var/obj/item/weapon/tank/T = A - atmosanalyzer_scan(T.air_contents, user, T) - else if (istype(A, /obj/machinery/portable_atmospherics)) - var/obj/machinery/portable_atmospherics/T = A - atmosanalyzer_scan(T.air_contents, user, T) - else if (istype(A, /obj/machinery/atmospherics/pipe)) - var/obj/machinery/atmospherics/pipe/T = A - atmosanalyzer_scan(T.parent.air, user, T) - else if (istype(A, /obj/machinery/power/rad_collector)) - var/obj/machinery/power/rad_collector/T = A - if(T.P) atmosanalyzer_scan(T.P.air_contents, user, T) - else if (istype(A, /obj/item/weapon/flamethrower)) - var/obj/item/weapon/flamethrower/T = A - if(T.ptank) atmosanalyzer_scan(T.ptank.air_contents, user, T) - else if (istype(A, /obj/machinery/portable_atmospherics/scrubber/huge)) - var/obj/machinery/portable_atmospherics/scrubber/huge/T = A - atmosanalyzer_scan(T.air_contents, user, T) - else if (istype(A, /obj/machinery/atmospherics/unary/tank)) - var/obj/machinery/atmospherics/unary/tank/T = A - atmosanalyzer_scan(T.air_contents, user, T) - - if (!scanmode && istype(A, /obj/item/weapon/paper) && owner) - // JMO 20140705: Makes scanned document show up properly in the notes. Not pretty for formatted documents, - // as this will clobber the HTML, but at least it lets you scan a document. You can restore the original - // notes by editing the note again. (Was going to allow you to edit, but scanned documents are too long.) - var/raw_scan = (A:info) - var/formatted_scan = "" - // Scrub out the tags (replacing a few formatting ones along the way) - // Find the beginning and end of the first tag. - var/tag_start = findtext(raw_scan,"<") - var/tag_stop = findtext(raw_scan,">") - // Until we run out of complete tags... - while(tag_start&&tag_stop) - var/pre = copytext(raw_scan,1,tag_start) // Get the stuff that comes before the tag - var/tag = lowertext(copytext(raw_scan,tag_start+1,tag_stop)) // Get the tag so we can do intellegent replacement - var/tagend = findtext(tag," ") // Find the first space in the tag if there is one. - // Anything that's before the tag can just be added as is. - formatted_scan = formatted_scan+pre - // If we have a space after the tag (and presumably attributes) just crop that off. - if (tagend) - tag=copytext(tag,1,tagend) - if (tag=="p"||tag=="/p"||tag=="br") // Check if it's I vertical space tag. - formatted_scan=formatted_scan+"
" // If so, add some padding in. - raw_scan = copytext(raw_scan,tag_stop+1) // continue on with the stuff after the tag - // Look for the next tag in what's left - tag_start = findtext(raw_scan,"<") - tag_stop = findtext(raw_scan,">") - // Anything that is left in the page. just tack it on to the end as is - formatted_scan=formatted_scan+raw_scan - // If there is something in there already, pad it out. - if (length(note)>0) - note = note + "

" - // Store the scanned document to the notes - note = "Scanned Document. Edit to restore previous notes/delete scan.
----------
" + formatted_scan + "
" - // notehtml ISN'T set to allow user to get their old notes back. A better implementation would add a "scanned documents" - // feature to the PDA, which would better convey the availability of the feature, but this will work for now. - // Inform the user - user << "\blue Paper scanned and OCRed to notekeeper." //concept of scanning paper copyright brainoblivion 2009 + if(proximity && scanmode) + scanmode.scan_atom(A, user) /obj/item/device/pda/proc/explode() //This needs tuning. if(!src.detonate) return @@ -1212,64 +427,7 @@ var/global/list/obj/item/device/pda/PDAs = list() src.pai.loc = get_turf(src.loc) return ..() -/obj/item/device/pda/clown/Crossed(AM as mob|obj) //Clown PDA is slippery. - if (istype(AM, /mob/living/carbon)) - var/mob/living/carbon/M = AM - M.slip("pda", 8, 5, 0, 1) - -/obj/item/device/pda/proc/available_pdas() - var/list/names = list() - var/list/plist = list() - var/list/namecounts = list() - - if (toff) - usr << "Turn on your receiver in order to send messages." - return - - for (var/obj/item/device/pda/P in PDAs) - if (!P.owner) - continue - else if(P.hidden) - continue - else if (P == src) - continue - else if (P.toff) - continue - - var/name = P.owner - if (name in names) - namecounts[name]++ - name = text("[name] ([namecounts[name]])") - else - names.Add(name) - namecounts[name] = 1 - - plist[text("[name]")] = P - return plist - -//Some spare PDAs in a box -/obj/item/weapon/storage/box/PDAs - name = "spare PDAs" - desc = "A box of spare PDA microcomputers." - icon = 'icons/obj/pda.dmi' - icon_state = "pdabox" - - New() - ..() - new /obj/item/device/pda(src) - new /obj/item/device/pda(src) - new /obj/item/device/pda(src) - new /obj/item/device/pda(src) - new /obj/item/weapon/cartridge/head(src) - - var/newcart = pick( /obj/item/weapon/cartridge/engineering, - /obj/item/weapon/cartridge/security, - /obj/item/weapon/cartridge/medical, - /obj/item/weapon/cartridge/signal/toxins, - /obj/item/weapon/cartridge/quartermaster) - new newcart(src) - // 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) + A.emp_act(severity) \ No newline at end of file diff --git a/code/game/objects/items/devices/PDA/ai.dm b/code/game/objects/items/devices/PDA/ai.dm new file mode 100644 index 00000000000..65386f81387 --- /dev/null +++ b/code/game/objects/items/devices/PDA/ai.dm @@ -0,0 +1,91 @@ +// Special AI/pAI PDAs that cannot explode. +/obj/item/device/pda/ai + icon_state = "NONE" + detonate = 0 + ttone = "data" + +/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 + ")" + +/obj/item/device/pda/ai/verb/cmd_send_pdamesg() + set category = "AI IM" + set name = "Send PDA Message" + set src in usr + + if(usr.stat == 2) + usr << "You can't send PDA messages because you are dead!" + return + var/datum/data/pda/app/messenger/M = find_program(/datum/data/pda/app/messenger) + if(!M) + usr << "Cannot use messenger!" + var/list/plist = M.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] + M.create_message(usr, selected) + +/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) + 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) + if(!M) + usr << "Cannot use messenger!" + var/HTML = "AI PDA Message Log" + for(var/index in M.tnote) + if(index["sent"]) + HTML += addtext("→ To ", index["owner"],":
", index["message"], "
") + else + HTML += addtext("← From ", index["owner"],":
", index["message"], "
") + HTML +="" + usr << browse(HTML, "window=log;size=400x444;border=1;can_resize=1;can_close=1;can_minimize=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) + 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.toff = !M.toff + usr << "PDA sender/receiver toggled [(M.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) + 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")]!" + +/obj/item/device/pda/ai/can_use() + return 1 + + +/obj/item/device/pda/ai/attack_self(mob/user as mob) + if ((honkamt > 0) && (prob(60)))//For clown virus. + honkamt-- + playsound(loc, 'sound/items/bikehorn.ogg', 30, 1) + return + +/obj/item/device/pda/ai/pai + ttone = "assist" \ No newline at end of file diff --git a/code/game/objects/items/devices/PDA/app.dm b/code/game/objects/items/devices/PDA/app.dm new file mode 100644 index 00000000000..5d322b80c2f --- /dev/null +++ b/code/game/objects/items/devices/PDA/app.dm @@ -0,0 +1,62 @@ +// Base class for anything that can show up on home screen +/datum/data/pda + var/icon = "tasks" + 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 + +/datum/data/pda/proc/start() + + +// An app has a button on the home screen and its own UI +/datum/data/pda/app + name = "App" + size = 3 + var/title = null // what is displayed in the title bar when this is the current app + var/template = "" + var/update = PDA_APP_UPDATE + var/has_back = 0 + +/datum/data/pda/app/New() + if(!title) + title = name + +/datum/data/pda/app/start() + pda.current_app = src + return 1 + +/datum/data/pda/app/proc/update_ui(mob/user as mob, list/data) + + +// Utilities just have a button on the home screen, but custom code when clicked +/datum/data/pda/utility + name = "Utility" + icon = "gear" + size = 1 + category = "Utilities" + + +/datum/data/pda/utility/scanmode + var/base_name + category = "Scanners" + +/datum/data/pda/utility/scanmode/New(obj/item/weapon/cartridge/C) + ..(C) + name = "Enable [base_name]" + +/datum/data/pda/utility/scanmode/start() + if(pda.scanmode) + pda.scanmode.name = "Enable [pda.scanmode.base_name]" + + if(pda.scanmode == src) + pda.scanmode = null + else + pda.scanmode = src + name = "Disable [base_name]" + + pda.update_shortcuts() + return 1 + +/datum/data/pda/utility/scanmode/proc/scan_mob(mob/living/C as mob, mob/living/user as mob) + +/datum/data/pda/utility/scanmode/proc/scan_atom(atom/A as mob|obj|turf|area, mob/user as mob) \ No newline at end of file diff --git a/code/game/objects/items/devices/PDA/cart.dm b/code/game/objects/items/devices/PDA/cart.dm index 2f5790c5fbb..bf5e5902dd8 100644 --- a/code/game/objects/items/devices/PDA/cart.dm +++ b/code/game/objects/items/devices/PDA/cart.dm @@ -7,57 +7,55 @@ w_class = 1 var/obj/item/radio/integrated/radio = null - var/access_security = 0 - var/access_engine = 0 - var/access_atmos = 0 - var/access_medical = 0 - var/access_clown = 0 - var/access_mime = 0 - var/access_janitor = 0 -// var/access_flora = 0 - var/access_reagent_scanner = 0 - var/access_remote_door = 0 // Control some blast doors remotely!! - var/remote_door_id = "" - var/access_status_display = 0 - var/access_quartermaster = 0 - var/access_detonate_pda = 0 - var/access_hydroponics = 0 + var/charges = 0 - var/mode = null - var/menu - var/datum/data/record/active1 = null //General - var/datum/data/record/active2 = null //Medical - var/datum/data/record/active3 = null //Security - var/obj/machinery/computer/monitor/powmonitor = null // Power Monitor - var/list/powermonitors = list() - var/message1 // used for status_displays - var/message2 + var/list/stored_data = list() + var/list/programs = list() + var/list/messenger_plugins = list() + +/obj/item/weapon/cartridge/New() + if(ticker && ticker.current_state >= GAME_STATE_SETTING_UP) + initialize() + +/obj/item/weapon/cartridge/proc/update_programs(obj/item/device/pda/pda) + for(var/datum/data/pda/P in programs) + P.pda = pda + for(var/datum/data/pda/messenger_plugin/P in messenger_plugins) + P.pda = pda /obj/item/weapon/cartridge/engineering name = "Power-ON Cartridge" icon_state = "cart-e" - access_engine = 1 + programs = list( + new/datum/data/pda/app/power, + new/datum/data/pda/utility/scanmode/halogen) /obj/item/weapon/cartridge/atmos name = "BreatheDeep Cartridge" icon_state = "cart-a" - access_atmos = 1 + programs = list( + new/datum/data/pda/utility/scanmode/gas) /obj/item/weapon/cartridge/medical name = "Med-U Cartridge" icon_state = "cart-m" - access_medical = 1 + programs = list( + new/datum/data/pda/app/crew_records/medical, + new/datum/data/pda/utility/scanmode/medical) /obj/item/weapon/cartridge/chemistry name = "ChemWhiz Cartridge" icon_state = "cart-chem" - access_reagent_scanner = 1 + programs = list( + new/datum/data/pda/utility/scanmode/reagent) /obj/item/weapon/cartridge/security name = "R.O.B.U.S.T. Cartridge" icon_state = "cart-s" - access_security = 1 + programs = list( + new/datum/data/pda/app/crew_records/security, + new/datum/data/pda/app/secbot_control) /obj/item/weapon/cartridge/security/initialize() radio = new /obj/item/radio/integrated/beepsky(src) @@ -66,32 +64,42 @@ /obj/item/weapon/cartridge/detective name = "D.E.T.E.C.T. Cartridge" icon_state = "cart-s" - access_security = 1 - access_medical = 1 + programs = list( + new/datum/data/pda/app/crew_records/medical, + new/datum/data/pda/utility/scanmode/medical, + + new/datum/data/pda/app/crew_records/security) /obj/item/weapon/cartridge/janitor name = "CustodiPRO Cartridge" desc = "The ultimate in clean-room design." icon_state = "cart-j" - access_janitor = 1 + programs = list( + new/datum/data/pda/app/janitor) /obj/item/weapon/cartridge/lawyer name = "P.R.O.V.E. Cartridge" icon_state = "cart-s" - access_security = 1 + programs = list( + new/datum/data/pda/app/crew_records/security) /obj/item/weapon/cartridge/clown name = "Honkworks 5.0" icon_state = "cart-clown" - access_clown = 1 charges = 5 + programs = list( + new/datum/data/pda/utility/honk) + messenger_plugins = list( + new/datum/data/pda/messenger_plugin/virus/clown) /obj/item/weapon/cartridge/mime name = "Gestur-O 1000" icon_state = "cart-mi" - access_mime = 1 charges = 5 + messenger_plugins = list( + new/datum/data/pda/messenger_plugin/virus/mime) + /* /obj/item/weapon/cartridge/botanist name = "Green Thumb v4.20" @@ -102,13 +110,8 @@ /obj/item/weapon/cartridge/signal name = "generic signaler cartridge" desc = "A data cartridge with an integrated radio signaler module." - -/obj/item/weapon/cartridge/signal/toxins - name = "Signal Ace 2" - desc = "Complete with integrated radio signaler!" - icon_state = "cart-tox" - access_reagent_scanner = 1 - access_atmos = 1 + programs = list( + new/datum/data/pda/app/signaller) /obj/item/weapon/cartridge/signal/initialize() radio = new /obj/item/radio/integrated/signal(src) @@ -118,11 +121,24 @@ qdel(radio) return ..() +/obj/item/weapon/cartridge/signal/toxins + name = "Signal Ace 2" + desc = "Complete with integrated radio signaler!" + icon_state = "cart-tox" + programs = list( + new/datum/data/pda/utility/scanmode/gas, + + new/datum/data/pda/utility/scanmode/reagent, + + new/datum/data/pda/app/signaller) + /obj/item/weapon/cartridge/quartermaster name = "Space Parts & Space Vendors Cartridge" desc = "Perfect for the Quartermaster on the go!" icon_state = "cart-q" - access_quartermaster = 1 + programs = list( + new/datum/data/pda/app/supply, + new/datum/data/pda/app/mule_control) /obj/item/weapon/cartridge/quartermaster/initialize() radio = new /obj/item/radio/integrated/mule(src) @@ -131,15 +147,21 @@ /obj/item/weapon/cartridge/head name = "Easy-Record DELUXE" icon_state = "cart-h" - access_status_display = 1 + programs = list( + new/datum/data/pda/app/status_display) /obj/item/weapon/cartridge/hop name = "HumanResources9001" icon_state = "cart-h" - access_status_display = 1 - access_quartermaster = 1 - access_janitor = 1 - access_security = 1 + programs = list( + new/datum/data/pda/app/crew_records/security, + + new/datum/data/pda/app/janitor, + + new/datum/data/pda/app/supply, + new/datum/data/pda/app/mule_control, + + new/datum/data/pda/app/status_display) /obj/item/weapon/cartridge/hop/initialize() radio = new /obj/item/radio/integrated/mule(src) @@ -148,8 +170,11 @@ /obj/item/weapon/cartridge/hos name = "R.O.B.U.S.T. DELUXE" icon_state = "cart-hos" - access_status_display = 1 - access_security = 1 + programs = list( + new/datum/data/pda/app/crew_records/security, + new/datum/data/pda/app/secbot_control, + + new/datum/data/pda/app/status_display) /obj/item/weapon/cartridge/hos/initialize() radio = new /obj/item/radio/integrated/beepsky(src) @@ -158,23 +183,36 @@ /obj/item/weapon/cartridge/ce name = "Power-On DELUXE" icon_state = "cart-ce" - access_status_display = 1 - access_engine = 1 - access_atmos = 1 + programs = list( + new/datum/data/pda/app/power, + new/datum/data/pda/utility/scanmode/halogen, + + new/datum/data/pda/utility/scanmode/gas, + + new/datum/data/pda/app/status_display) /obj/item/weapon/cartridge/cmo name = "Med-U DELUXE" icon_state = "cart-cmo" - access_status_display = 1 - access_reagent_scanner = 1 - access_medical = 1 + programs = list( + new/datum/data/pda/app/crew_records/medical, + new/datum/data/pda/utility/scanmode/medical, + + new/datum/data/pda/utility/scanmode/reagent, + + new/datum/data/pda/app/status_display) /obj/item/weapon/cartridge/rd name = "Signal Ace DELUXE" icon_state = "cart-rd" - access_status_display = 1 - access_reagent_scanner = 1 - access_atmos = 1 + programs = list( + new/datum/data/pda/utility/scanmode/gas, + + new/datum/data/pda/utility/scanmode/reagent, + + new/datum/data/pda/app/signaller, + + new/datum/data/pda/app/status_display) /obj/item/weapon/cartridge/rd/initialize() radio = new /obj/item/radio/integrated/signal(src) @@ -184,14 +222,25 @@ name = "Value-PAK Cartridge" desc = "Now with 200% more value!" icon_state = "cart-c" - access_quartermaster = 1 - access_janitor = 1 - access_engine = 1 - access_security = 1 - access_medical = 1 - access_reagent_scanner = 1 - access_status_display = 1 - access_atmos = 1 + programs = list( + new/datum/data/pda/app/power, + new/datum/data/pda/utility/scanmode/halogen, + + new/datum/data/pda/utility/scanmode/gas, + + new/datum/data/pda/app/crew_records/medical, + new/datum/data/pda/utility/scanmode/medical, + + new/datum/data/pda/utility/scanmode/reagent, + + new/datum/data/pda/app/crew_records/security, + new/datum/data/pda/app/secbot_control, + + new/datum/data/pda/app/janitor, + + new/datum/data/pda/app/supply, + + new/datum/data/pda/app/status_display) /obj/item/weapon/cartridge/captain/initialize() radio = new /obj/item/radio/integrated/beepsky(src) @@ -200,21 +249,35 @@ /obj/item/weapon/cartridge/supervisor name = "Easy-Record DELUXE" icon_state = "cart-h" - access_status_display = 1 - access_security = 1 + programs = list( + new/datum/data/pda/app/crew_records/security, + + new/datum/data/pda/app/status_display) /obj/item/weapon/cartridge/centcom name = "Value-PAK Cartridge" desc = "Now with 200% more value!" icon_state = "cart-c" - access_quartermaster = 1 - access_janitor = 1 - access_engine = 1 - access_security = 1 - access_medical = 1 - access_reagent_scanner = 1 - access_status_display = 1 - access_atmos = 1 + programs = list( + new/datum/data/pda/app/power, + new/datum/data/pda/utility/scanmode/halogen, + + new/datum/data/pda/utility/scanmode/gas, + + new/datum/data/pda/app/crew_records/medical, + new/datum/data/pda/utility/scanmode/medical, + + new/datum/data/pda/utility/scanmode/reagent, + + new/datum/data/pda/app/crew_records/security, + new/datum/data/pda/app/secbot_control, + + new/datum/data/pda/app/janitor, + + new/datum/data/pda/app/supply, + new/datum/data/pda/app/mule_control, + + new/datum/data/pda/app/status_display) /obj/item/weapon/cartridge/centcom/initialize() radio = new /obj/item/radio/integrated/beepsky(src) @@ -223,390 +286,14 @@ /obj/item/weapon/cartridge/syndicate name = "Detomatix Cartridge" icon_state = "cart" - access_remote_door = 1 - access_detonate_pda = 1 - remote_door_id = "smindicate" //Make sure this matches the syndicate shuttle's shield/door id!! //don't ask about the name, testing. + var/initial_remote_door_id = "smindicate" //Make sure this matches the syndicate shuttle's shield/door id!! //don't ask about the name, testing. charges = 4 - -/obj/item/weapon/cartridge/proc/post_status(var/command, var/data1, var/data2) - - var/datum/radio_frequency/frequency = radio_controller.return_frequency(1435) - if(!frequency) return - - var/datum/signal/status_signal = new - status_signal.source = src - status_signal.transmission_method = 1 - status_signal.data["command"] = command - - switch(command) - if("message") - status_signal.data["msg1"] = data1 - status_signal.data["msg2"] = data2 - if(loc) - var/obj/item/PDA = loc - var/mob/user = PDA.fingerprintslast - if(istype(PDA.loc,/mob/living)) - name = PDA.loc - log_admin("STATUS: [user] set status screen with [PDA]. Message: [data1] [data2]") - message_admins("STATUS: [user] set status screen with [PDA]. Message: [data1] [data2]") - - if("alert") - status_signal.data["picture_state"] = data1 - - frequency.post_signal(src, status_signal) - - -/* - This generates the nano values of the cart menus. - Because we close the UI when we insert a new cart - we don't have to worry about null values on items - the user can't access. Well, unless they are href hacking. - But in that case their UI will just lock up. -*/ - - -/obj/item/weapon/cartridge/proc/create_NanoUI_values(mob/user as mob) - var/values[0] - - /* Signaler (Mode: 40) */ - - - if(istype(radio,/obj/item/radio/integrated/signal) && (mode==40)) - var/obj/item/radio/integrated/signal/R = radio - values["signal_freq"] = format_frequency(R.frequency) - values["signal_code"] = R.code - - - /* Station Display (Mode: 42) */ - - if(mode==42) - values["message1"] = message1 ? message1 : "(none)" - values["message2"] = message2 ? message2 : "(none)" - - - - /* Power Monitor (Mode: 43 / 433) */ - if(mode==43 || mode==433) - values["powermonitors"] = powermonitor_repository.powermonitor_data() - - if (powmonitor && !isnull(powmonitor.powernet)) - values["powerconnected"] = 1 - values["poweravail"] = powmonitor.powernet.avail - values["powerload"] = num2text(powmonitor.powernet.viewload,10) - values["powerdemand"] = powmonitor.powernet.load - values["apcs"] = apc_repository.apc_data(powmonitor) - else - values["powerconnected"] = 0 - - - - - - /* General Records (Mode: 44 / 441 / 45 / 451) */ - if(mode == 44 || mode == 441 || mode == 45 || mode ==451) - if(istype(active1, /datum/data/record) && (active1 in data_core.general)) - values["general"] = active1.fields - values["general_exists"] = 1 - - else - - values["general_exists"] = 0 - - - - /* Medical Records (Mode: 44 / 441) */ - - if(mode == 44 || mode == 441) - var/medData[0] - for(var/datum/data/record/R in sortRecord(data_core.general)) - medData[++medData.len] = list(Name = R.fields["name"],"ref" = "\ref[R]") - values["medical_records"] = medData - - if(istype(active2, /datum/data/record) && (active2 in data_core.medical)) - values["medical"] = active2.fields - values["medical_exists"] = 1 - else - values["medical_exists"] = 0 - - /* Security Records (Mode:45 / 451) */ - - if(mode == 45 || mode == 451) - var/secData[0] - for (var/datum/data/record/R in sortRecord(data_core.general)) - secData[++secData.len] = list(Name = R.fields["name"], "ref" = "\ref[R]") - values["security_records"] = secData - - if(istype(active3, /datum/data/record) && (active3 in data_core.security)) - values["security"] = active3.fields - values["security_exists"] = 1 - else - values["security_exists"] = 0 - - /* Security Bot Control (Mode: 46) */ - - if(mode==46) - var/botsData[0] - var/beepskyData[0] - if(istype(radio,/obj/item/radio/integrated/beepsky)) - var/obj/item/radio/integrated/beepsky/SC = radio - beepskyData["active"] = SC.active - if(SC.active && !isnull(SC.botstatus)) - var/area/loca = SC.botstatus["loca"] - var/loca_name = sanitize(loca.name) - beepskyData["botstatus"] = list("loca" = loca_name, "mode" = SC.botstatus["mode"]) - else - beepskyData["botstatus"] = list("loca" = null, "mode" = -1) - var/botsCount=0 - if(SC.botlist && SC.botlist.len) - for(var/obj/machinery/bot/B in SC.botlist) - botsCount++ - if(B.loc) - botsData[++botsData.len] = list("Name" = sanitize(B.name), "Location" = sanitize(B.loc.loc.name), "ref" = "\ref[B]") - - if(!botsData.len) - botsData[++botsData.len] = list("Name" = "No bots found", "Location" = "Invalid", "ref"= null) - - beepskyData["bots"] = botsData - beepskyData["count"] = botsCount - - else - beepskyData["active"] = 0 - botsData[++botsData.len] = list("Name" = "No bots found", "Location" = "Invalid", "ref"= null) - beepskyData["botstatus"] = list("loca" = null, "mode" = null) - beepskyData["bots"] = botsData - beepskyData["count"] = 0 - - values["beepsky"] = beepskyData - - - /* MULEBOT Control (Mode: 48) */ - - if(mode==48) - var/muleData[0] - var/mulebotsData[0] - if(istype(radio,/obj/item/radio/integrated/mule)) - var/obj/item/radio/integrated/mule/QC = radio - muleData["active"] = QC.active - if(QC.active && !isnull(QC.botstatus)) - var/area/loca = QC.botstatus["loca"] - var/loca_name = sanitize(loca.name) - muleData["botstatus"] = list("loca" = loca_name, "mode" = QC.botstatus["mode"],"home"=QC.botstatus["home"],"powr" = QC.botstatus["powr"],"retn" =QC.botstatus["retn"], "pick"=QC.botstatus["pick"], "load" = QC.botstatus["load"], "dest" = sanitize(QC.botstatus["dest"])) - - else - muleData["botstatus"] = list("loca" = null, "mode" = -1,"home"=null,"powr" = null,"retn" =null, "pick"=null, "load" = null, "dest" = null) - - - var/mulebotsCount=0 - for(var/obj/machinery/bot/B in QC.botlist) - mulebotsCount++ - if(B.loc) - mulebotsData[++mulebotsData.len] = list("Name" = sanitize(B.name), "Location" = sanitize(B.loc.loc.name), "ref" = "\ref[B]") - - if(!mulebotsData.len) - mulebotsData[++mulebotsData.len] = list("Name" = "No bots found", "Location" = "Invalid", "ref"= null) - - muleData["bots"] = mulebotsData - muleData["count"] = mulebotsCount - - else - muleData["botstatus"] = list("loca" = null, "mode" = -1,"home"=null,"powr" = null,"retn" =null, "pick"=null, "load" = null, "dest" = null) - muleData["active"] = 0 - mulebotsData[++mulebotsData.len] = list("Name" = "No bots found", "Location" = "Invalid", "ref"= null) - muleData["bots"] = mulebotsData - muleData["count"] = 0 - - values["mulebot"] = muleData - - - - /* Supply Shuttle Requests Menu (Mode: 47) */ - - if(mode==47) - var/supplyData[0] - - if(shuttle_master.supply.mode == SHUTTLE_CALL) - supplyData["shuttle_moving"] = 1 - - if(shuttle_master.supply.z != ZLEVEL_STATION) - supplyData["shuttle_loc"] = "station" - else - supplyData["shuttle_loc"] = "centcom" - - supplyData["shuttle_time"] = "([shuttle_master.supply.timeLeft(600)] Mins)" - - var/supplyOrderCount = 0 - var/supplyOrderData[0] - for(var/S in shuttle_master.shoppinglist) - var/datum/supply_order/SO = S - supplyOrderData[++supplyOrderData.len] = list("Number" = SO.ordernum, "Name" = html_encode(SO.object.name), "ApprovedBy" = SO.orderedby, "Comment" = html_encode(SO.comment)) - - if(!supplyOrderData.len) - supplyOrderData[++supplyOrderData.len] = list("Number" = null, "Name" = null, "OrderedBy"=null) - - supplyData["approved"] = supplyOrderData - supplyData["approved_count"] = supplyOrderCount - - var/requestCount = 0 - var/requestData[0] - for(var/S in shuttle_master.requestlist) - var/datum/supply_order/SO = S - requestCount++ - requestData[++requestData.len] = list("Number" = SO.ordernum, "Name" = html_encode(SO.object.name), "OrderedBy" = SO.orderedby, "Comment" = html_encode(SO.comment)) - - if(!requestData.len) - requestData[++requestData.len] = list("Number" = null, "Name" = null, "orderedBy" = null, "Comment" = null) - - supplyData["requests"] = requestData - supplyData["requests_count"] = requestCount - - - values["supply"] = supplyData - - - - /* Janitor Supplies Locator (Mode: 49) */ - if(mode==49) - var/JaniData[0] - var/turf/cl = get_turf(src) - - if(cl) - JaniData["user_loc"] = list("x" = cl.x, "y" = cl.y) - else - JaniData["user_loc"] = list("x" = 0, "y" = 0) - var/MopData[0] - for(var/obj/item/weapon/mop/M in janitorial_equipment) - var/turf/ml = get_turf(M) - if(ml) - if(ml.z != cl.z) - continue - var/direction = get_dir(src, M) - MopData[++MopData.len] = list ("x" = ml.x, "y" = ml.y, "dir" = uppertext(dir2text(direction)), "status" = M.reagents.total_volume ? "Wet" : "Dry") - - if(!MopData.len) - MopData[++MopData.len] = list("x" = 0, "y" = 0, dir=null, status = null) - - - var/BucketData[0] - for(var/obj/structure/mopbucket/B in janitorial_equipment) - var/turf/bl = get_turf(B) - if(bl) - if(bl.z != cl.z) - continue - var/direction = get_dir(src,B) - BucketData[++BucketData.len] = list ("x" = bl.x, "y" = bl.y, "dir" = uppertext(dir2text(direction)), "status" = B.reagents.total_volume/100) - - if(!BucketData.len) - BucketData[++BucketData.len] = list("x" = 0, "y" = 0, dir=null, status = null) - - var/CbotData[0] - for(var/obj/machinery/bot/cleanbot/B in aibots) - var/turf/bl = get_turf(B) - if(bl) - if(bl.z != cl.z) - continue - var/direction = get_dir(src,B) - CbotData[++CbotData.len] = list("x" = bl.x, "y" = bl.y, "dir" = uppertext(dir2text(direction)), "status" = B.on ? "Online" : "Offline") - - - if(!CbotData.len) - CbotData[++CbotData.len] = list("x" = 0, "y" = 0, dir=null, status = null) - var/CartData[0] - for(var/obj/structure/janitorialcart/B in janitorial_equipment) - var/turf/bl = get_turf(B) - if(bl) - if(bl.z != cl.z) - continue - var/direction = get_dir(src,B) - CartData[++CartData.len] = list("x" = bl.x, "y" = bl.y, "dir" = uppertext(dir2text(direction)), "status" = B.reagents.total_volume/100) - if(!CartData.len) - CartData[++CartData.len] = list("x" = 0, "y" = 0, dir=null, status = null) - - - - - JaniData["mops"] = MopData - JaniData["buckets"] = BucketData - JaniData["cleanbots"] = CbotData - JaniData["carts"] = CartData - values["janitor"] = JaniData - - return values - - - - - -/obj/item/weapon/cartridge/Topic(href, href_list) - ..() - - if (!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr)) - usr.unset_machine() - usr << browse(null, "window=pda") - return - - - - - switch(href_list["choice"]) - if("Medical Records") - var/datum/data/record/R = locate(href_list["target"]) - var/datum/data/record/M = locate(href_list["target"]) - loc:mode = 441 - mode = 441 - if (R in data_core.general) - for (var/datum/data/record/E in data_core.medical) - if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"])) - M = E - break - active1 = R - active2 = M - - if("Security Records") - var/datum/data/record/R = locate(href_list["target"]) - var/datum/data/record/S = locate(href_list["target"]) - loc:mode = 451 - mode = 451 - if (R in data_core.general) - for (var/datum/data/record/E in data_core.security) - if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"])) - S = E - break - active1 = R - active3 = S - - if("Send Signal") - spawn( 0 ) - radio:send_signal("ACTIVATE") - return - - if("Signal Frequency") - var/new_frequency = sanitize_frequency(radio:frequency + text2num(href_list["sfreq"])) - radio:set_frequency(new_frequency) - - if("Signal Code") - radio:code += text2num(href_list["scode"]) - radio:code = round(radio:code) - radio:code = min(100, radio:code) - radio:code = max(1, radio:code) - - if("Status") - switch(href_list["statdisp"]) - if("message") - post_status("message", message1, message2) - if("alert") - post_status("alert", href_list["alert"]) - if("setmsg1") - message1 = input("Line 1", "Enter Message Text", message1) as text|null - updateSelfDialog() - if("setmsg2") - message2 = input("Line 2", "Enter Message Text", message2) as text|null - updateSelfDialog() - else - post_status(href_list["statdisp"]) - if("Power Select") - var/pref = href_list["target"] - powmonitor = locate(pref) - loc:mode = 433 - mode = 433 - - return 1 + programs = list( + new/datum/data/pda/utility/toggle_door) + messenger_plugins = list( + new/datum/data/pda/messenger_plugin/virus/detonate) + +/obj/item/weapon/cartridge/syndicate/New() + var/datum/data/pda/utility/toggle_door/D = programs[1] + if(istype(D)) + D.remote_door_id = initial_remote_door_id \ No newline at end of file diff --git a/code/game/objects/items/devices/PDA/cart_apps.dm b/code/game/objects/items/devices/PDA/cart_apps.dm new file mode 100644 index 00000000000..365083c0a48 --- /dev/null +++ b/code/game/objects/items/devices/PDA/cart_apps.dm @@ -0,0 +1,415 @@ +/datum/data/pda/app/status_display + name = "Status Display" + icon = "list-alt" + template = "pda_status_display" + category = "Utilities" + + var/message1 // used for status_displays + var/message2 + +/datum/data/pda/app/status_display/update_ui(mob/user as mob, list/data) + data["records"] = list( + "message1" = message1 ? message1 : "(none)", + "message2" = message2 ? message2 : "(none)") + +/datum/data/pda/app/status_display/Topic(href, list/href_list) + switch(href_list["choice"]) + if("Status") + switch(href_list["statdisp"]) + if("message") + post_status("message", message1, message2) + if("alert") + post_status("alert", href_list["alert"]) + if("setmsg1") + message1 = input("Line 1", "Enter Message Text", message1) as text|null + if("setmsg2") + message2 = input("Line 2", "Enter Message Text", message2) as text|null + else + post_status(href_list["statdisp"]) + +/datum/data/pda/app/status_display/proc/post_status(var/command, var/data1, var/data2) + var/datum/radio_frequency/frequency = radio_controller.return_frequency(1435) + if(!frequency) + return + + var/datum/signal/status_signal = new + status_signal.source = src + status_signal.transmission_method = 1 + status_signal.data["command"] = command + + switch(command) + if("message") + status_signal.data["msg1"] = data1 + status_signal.data["msg2"] = data2 + var/mob/user = pda.fingerprintslast + if(istype(pda.loc, /mob/living)) + name = pda.loc + log_admin("STATUS: [user] set status screen with [pda]. Message: [data1] [data2]") + message_admins("STATUS: [user] set status screen with [pda]. Message: [data1] [data2]") + + if("alert") + status_signal.data["picture_state"] = data1 + + spawn(0) + frequency.post_signal(src, status_signal) + + +/datum/data/pda/app/signaller + name = "Signaler System" + icon = "rss" + template = "pda_signaller" + category = "Utilities" + +/datum/data/pda/app/signaller/update_ui(mob/user as mob, list/data) + if(pda.cartridge && istype(pda.cartridge.radio, /obj/item/radio/integrated/signal)) + var/obj/item/radio/integrated/signal/R = pda.cartridge.radio + data["signal_freq"] = format_frequency(R.frequency) + data["signal_code"] = R.code + +/datum/data/pda/app/signaller/Topic(href, list/href_list) + if(pda.cartridge && istype(pda.cartridge.radio, /obj/item/radio/integrated/signal)) + var/obj/item/radio/integrated/signal/R = pda.cartridge.radio + + switch(href_list["choice"]) + if("Send Signal") + spawn(0) + R.send_signal("ACTIVATE") + + if("Signal Frequency") + var/new_frequency = sanitize_frequency(R.frequency + text2num(href_list["sfreq"])) + R.set_frequency(new_frequency) + + if("Signal Code") + R.code += text2num(href_list["scode"]) + R.code = round(R.code) + R.code = min(100, R.code) + R.code = max(1, R.code) + +/datum/data/pda/app/power + name = "Power Monitor" + icon = "exclamation-triangle" + template = "pda_power" + category = "Engineering" + update = PDA_APP_UPDATE_SLOW + + var/obj/machinery/computer/monitor/powmonitor = null + +/datum/data/pda/app/power/update_ui(mob/user as mob, list/data) + if (powmonitor && !isnull(powmonitor.powernet)) + data["records"] = list( + "powerconnected" = 1, + "poweravail" = powmonitor.powernet.avail, + "powerload" = num2text(powmonitor.powernet.viewload, 10), + "powerdemand" = powmonitor.powernet.load, + "apcs" = apc_repository.apc_data(powmonitor)) + has_back = 1 + else + data["records"] = list( + "powerconnected" = 0, + "powermonitors" = powermonitor_repository.powermonitor_data()) + has_back = 0 + +/datum/data/pda/app/power/Topic(href, list/href_list) + switch(href_list["choice"]) + if("Power Select") + var/pref = href_list["target"] + powmonitor = locate(pref) + if("Back") + powmonitor = null + +/datum/data/pda/app/crew_records + var/datum/data/record/general_records = null + +/datum/data/pda/app/crew_records/update_ui(mob/user as mob, list/data) + var/list/records[0] + + if(general_records && general_records in data_core.general) + data["records"] = records + records["general"] = general_records.fields + return records + else + for(var/datum/data/record/R in sortRecord(data_core.general)) + records += list(list(Name = R.fields["name"], "ref" = "\ref[R]")) + data["recordsList"] = records + return null + +/datum/data/pda/app/crew_records/Topic(href, list/href_list) + switch(href_list["choice"]) + if("Records") + var/datum/data/record/R = locate(href_list["target"]) + if (R in data_core.general) + load_records(R) + if("Back") + general_records = null + has_back = 0 + +/datum/data/pda/app/crew_records/proc/load_records(datum/data/record/R) + general_records = R + has_back = 1 + +/datum/data/pda/app/crew_records/medical + name = "Medical Records" + icon = "heartbeat" + template = "pda_medical" + category = "Medical" + + var/datum/data/record/medical_records = null + +/datum/data/pda/app/crew_records/medical/update_ui(mob/user as mob, list/data) + var/list/records = ..() + if(!records) + return + + if(medical_records && medical_records in data_core.medical) + records["medical"] = medical_records.fields + + return records + +/datum/data/pda/app/crew_records/medical/load_records(datum/data/record/R) + ..(R) + for (var/datum/data/record/E in data_core.medical) + if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"])) + medical_records = E + break + +/datum/data/pda/app/crew_records/security + name = "Security Records" + icon = "tags" + template = "pda_security" + category = "Security" + + var/datum/data/record/security_records = null + +/datum/data/pda/app/crew_records/security/update_ui(mob/user as mob, list/data) + var/list/records = ..() + if(!records) + return + + if(security_records && security_records in data_core.security) + records["security"] = security_records.fields + + return records + +/datum/data/pda/app/crew_records/security/load_records(datum/data/record/R) + ..(R) + for (var/datum/data/record/E in data_core.security) + if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"])) + security_records = E + break + +/datum/data/pda/app/secbot_control + name = "Security Bot Access" + icon = "rss" + template = "pda_secbot" + category = "Security" + update = PDA_APP_UPDATE_SLOW + +/datum/data/pda/app/secbot_control/update_ui(mob/user as mob, list/data) + var/botsData[0] + var/beepskyData[0] + if(pda.cartridge && istype(pda.cartridge.radio, /obj/item/radio/integrated/beepsky)) + var/obj/item/radio/integrated/beepsky/SC = pda.cartridge.radio + beepskyData["active"] = SC.active ? SC.active.name : null + has_back = SC.active ? 1 : 0 + if(SC.active && !isnull(SC.botstatus)) + var/area/loca = SC.botstatus["loca"] + var/loca_name = sanitize(loca.name) + beepskyData["botstatus"] = list("loca" = loca_name, "mode" = SC.botstatus["mode"]) + else + beepskyData["botstatus"] = list("loca" = null, "mode" = -1) + var/botsCount=0 + if(SC.botlist && SC.botlist.len) + for(var/obj/machinery/bot/B in SC.botlist) + botsCount++ + if(B.loc) + botsData[++botsData.len] = list("Name" = sanitize(B.name), "Location" = sanitize(B.loc.loc.name), "ref" = "\ref[B]") + + if(!botsData.len) + botsData[++botsData.len] = list("Name" = "No bots found", "Location" = "Invalid", "ref"= null) + + beepskyData["bots"] = botsData + beepskyData["count"] = botsCount + + else + beepskyData["active"] = 0 + botsData[++botsData.len] = list("Name" = "No bots found", "Location" = "Invalid", "ref"= null) + beepskyData["botstatus"] = list("loca" = null, "mode" = null) + beepskyData["bots"] = botsData + beepskyData["count"] = 0 + has_back = 0 + + data["beepsky"] = beepskyData + +/datum/data/pda/app/secbot_control/Topic(href, list/href_list) + switch(href_list["choice"]) + if("Back") + if(pda.cartridge && istype(pda.cartridge.radio, /obj/item/radio/integrated/beepsky)) + pda.cartridge.radio.Topic(null, list(radiomenu = "1", op = "botlist")) + +/datum/data/pda/app/mule_control + name = "Delivery Bot Control" + icon = "truck" + template = "pda_mule" + category = "Quartermaster" + update = PDA_APP_UPDATE_SLOW + +/datum/data/pda/app/mule_control/update_ui(mob/user as mob, list/data) + var/muleData[0] + var/mulebotsData[0] + if(pda.cartridge && istype(pda.cartridge.radio, /obj/item/radio/integrated/mule)) + var/obj/item/radio/integrated/mule/QC = pda.cartridge.radio + muleData["active"] = QC.active ? sanitize(QC.active.name) : null + has_back = QC.active ? 1 : 0 + if(QC.active && !isnull(QC.botstatus)) + var/area/loca = QC.botstatus["loca"] + var/loca_name = sanitize(loca.name) + muleData["botstatus"] = list("loca" = loca_name, "mode" = QC.botstatus["mode"],"home"=QC.botstatus["home"],"powr" = QC.botstatus["powr"],"retn" =QC.botstatus["retn"], "pick"=QC.botstatus["pick"], "load" = QC.botstatus["load"], "dest" = sanitize(QC.botstatus["dest"])) + + else + muleData["botstatus"] = list("loca" = null, "mode" = -1,"home"=null,"powr" = null,"retn" =null, "pick"=null, "load" = null, "dest" = null) + + + var/mulebotsCount=0 + for(var/obj/machinery/bot/B in QC.botlist) + mulebotsCount++ + if(B.loc) + mulebotsData[++mulebotsData.len] = list("Name" = sanitize(B.name), "Location" = sanitize(B.loc.loc.name), "ref" = "\ref[B]") + + if(!mulebotsData.len) + mulebotsData[++mulebotsData.len] = list("Name" = "No bots found", "Location" = "Invalid", "ref"= null) + + muleData["bots"] = mulebotsData + muleData["count"] = mulebotsCount + + else + muleData["botstatus"] = list("loca" = null, "mode" = -1,"home"=null,"powr" = null,"retn" =null, "pick"=null, "load" = null, "dest" = null) + muleData["active"] = 0 + mulebotsData[++mulebotsData.len] = list("Name" = "No bots found", "Location" = "Invalid", "ref"= null) + muleData["bots"] = mulebotsData + muleData["count"] = 0 + has_back = 0 + + data["mulebot"] = muleData + +/datum/data/pda/app/mule_control/Topic(href, list/href_list) + switch(href_list["choice"]) + if("Back") + if(pda.cartridge && istype(pda.cartridge.radio, /obj/item/radio/integrated/mule)) + pda.cartridge.radio.Topic(null, list(radiomenu = "1", op = "botlist")) + +/datum/data/pda/app/supply + name = "Supply Records" + icon = "file-text-o" + template = "pda_supply" + category = "Quartermaster" + update = PDA_APP_UPDATE_SLOW + +/datum/data/pda/app/supply/update_ui(mob/user as mob, list/data) + var/supplyData[0] + + if(shuttle_master.supply.mode == SHUTTLE_CALL) + supplyData["shuttle_moving"] = 1 + + if(shuttle_master.supply.z != ZLEVEL_STATION) + supplyData["shuttle_loc"] = "station" + else + supplyData["shuttle_loc"] = "centcom" + + supplyData["shuttle_time"] = "([shuttle_master.supply.timeLeft(600)] Mins)" + + var/supplyOrderCount = 0 + var/supplyOrderData[0] + for(var/S in shuttle_master.shoppinglist) + var/datum/supply_order/SO = S + supplyOrderCount++ + supplyOrderData[++supplyOrderData.len] = list("Number" = SO.ordernum, "Name" = html_encode(SO.object.name), "ApprovedBy" = SO.orderedby, "Comment" = html_encode(SO.comment)) + + if(!supplyOrderData.len) + supplyOrderData[++supplyOrderData.len] = list("Number" = null, "Name" = null, "OrderedBy"=null) + + supplyData["approved"] = supplyOrderData + supplyData["approved_count"] = supplyOrderCount + + var/requestCount = 0 + var/requestData[0] + for(var/S in shuttle_master.requestlist) + var/datum/supply_order/SO = S + requestCount++ + requestData[++requestData.len] = list("Number" = SO.ordernum, "Name" = html_encode(SO.object.name), "OrderedBy" = SO.orderedby, "Comment" = html_encode(SO.comment)) + + if(!requestData.len) + requestData[++requestData.len] = list("Number" = null, "Name" = null, "orderedBy" = null, "Comment" = null) + + supplyData["requests"] = requestData + supplyData["requests_count"] = requestCount + + data["supply"] = supplyData + +/datum/data/pda/app/janitor + name = "Custodial Locator" + icon = "trash-o" + template = "pda_janitor" + category = "Utilities" + update = PDA_APP_UPDATE_SLOW + +/datum/data/pda/app/janitor/update_ui(mob/user as mob, list/data) + var/JaniData[0] + var/turf/cl = get_turf(pda) + + if(cl) + JaniData["user_loc"] = list("x" = cl.x, "y" = cl.y) + else + JaniData["user_loc"] = list("x" = 0, "y" = 0) + var/MopData[0] + for(var/obj/item/weapon/mop/M in janitorial_equipment) + var/turf/ml = get_turf(M) + if(ml) + if(ml.z != cl.z) + continue + var/direction = get_dir(pda, M) + MopData[++MopData.len] = list ("x" = ml.x, "y" = ml.y, "dir" = uppertext(dir2text(direction)), "status" = M.reagents.total_volume ? "Wet" : "Dry") + + if(!MopData.len) + MopData[++MopData.len] = list("x" = 0, "y" = 0, dir=null, status = null) + + + var/BucketData[0] + for(var/obj/structure/mopbucket/B in janitorial_equipment) + var/turf/bl = get_turf(B) + if(bl) + if(bl.z != cl.z) + continue + var/direction = get_dir(pda,B) + BucketData[++BucketData.len] = list ("x" = bl.x, "y" = bl.y, "dir" = uppertext(dir2text(direction)), "status" = B.reagents.total_volume/100) + + if(!BucketData.len) + BucketData[++BucketData.len] = list("x" = 0, "y" = 0, dir=null, status = null) + + var/CbotData[0] + for(var/obj/machinery/bot/cleanbot/B in aibots) + var/turf/bl = get_turf(B) + if(bl) + if(bl.z != cl.z) + continue + var/direction = get_dir(pda,B) + CbotData[++CbotData.len] = list("x" = bl.x, "y" = bl.y, "dir" = uppertext(dir2text(direction)), "status" = B.on ? "Online" : "Offline") + + + if(!CbotData.len) + CbotData[++CbotData.len] = list("x" = 0, "y" = 0, dir=null, status = null) + var/CartData[0] + for(var/obj/structure/janitorialcart/B in janitorial_equipment) + var/turf/bl = get_turf(B) + if(bl) + if(bl.z != cl.z) + continue + var/direction = get_dir(pda,B) + CartData[++CartData.len] = list("x" = bl.x, "y" = bl.y, "dir" = uppertext(dir2text(direction)), "status" = B.reagents.total_volume/100) + if(!CartData.len) + CartData[++CartData.len] = list("x" = 0, "y" = 0, dir=null, status = null) + + JaniData["mops"] = MopData + JaniData["buckets"] = BucketData + JaniData["cleanbots"] = CbotData + JaniData["carts"] = CartData + data["janitor"] = JaniData \ No newline at end of file diff --git a/code/game/objects/items/devices/PDA/core_apps.dm b/code/game/objects/items/devices/PDA/core_apps.dm new file mode 100644 index 00000000000..55a6dbd6f45 --- /dev/null +++ b/code/game/objects/items/devices/PDA/core_apps.dm @@ -0,0 +1,106 @@ +/datum/data/pda/app/main_menu + icon = "home" + template = "pda_main_menu" + hidden = 1 + +/datum/data/pda/app/main_menu/update_ui(mob/user as mob, list/data) + title = pda.name + + data["app"]["is_home"] = 1 + + data["apps"] = pda.shortcut_cache + data["categories"] = pda.shortcut_cat_order + data["pai"] = !isnull(pda.pai) // pAI inserted? + +/datum/data/pda/app/main_menu/Topic(href, list/href_list) + switch(href_list["choice"]) + if("UpdateInfo") + pda.ownjob = pda.id.assignment + pda.ownrank = pda.id.rank + pda.name = "PDA-[pda.owner] ([pda.ownjob])" + if("pai") + if(pda.pai) + if(pda.pai.loc != pda) + pda.pai = null + else + switch(href_list["option"]) + if("1") // Configure pAI device + pda.pai.attack_self(usr) + if("2") // Eject pAI device + var/turf/T = get_turf_or_move(pda.loc) + if(T) + pda.pai.loc = T + pda.pai = null + +/datum/data/pda/app/notekeeper + name = "Notekeeper" + icon = "sticky-note-o" + template = "pda_notekeeper" + + var/note = null + var/notehtml = "" + +/datum/data/pda/app/notekeeper/start() + . = ..() + if(!note) + note = "Congratulations, your station has chosen the [pda.model_name]!" + +/datum/data/pda/app/notekeeper/update_ui(mob/user as mob, list/data) + data["note"] = note // current pda notes + +/datum/data/pda/app/notekeeper/Topic(href, list/href_list) + switch(href_list["choice"]) + if("Edit") + var/n = input("Please enter message", name, notehtml) as message + if(pda.loc == usr) + note = adminscrub(n) + notehtml = html_decode(note) + note = replacetext(note, "\n", "
") + else + pda.close(usr) + +/datum/data/pda/app/manifest + name = "Crew Manifest" + icon = "user" + template = "pda_manifest" + update = PDA_APP_UPDATE_SLOW + +/datum/data/pda/app/manifest/update_ui(mob/user as mob, list/data) + data_core.get_manifest_json() + data["manifest"] = list("__json_cache" = ManifestJSON) + +/datum/data/pda/app/manifest/Topic(href, list/href_list) + +/datum/data/pda/app/atmos_scanner + name = "Atmospheric Scan" + icon = "fire" + template = "pda_atmos_scan" + category = "Utilities" + update = PDA_APP_UPDATE_SLOW + +/datum/data/pda/app/atmos_scanner/update_ui(mob/user as mob, list/data) + var/turf/T = get_turf(user.loc) + if(!isnull(T)) + var/datum/gas_mixture/environment = T.return_air() + + var/pressure = environment.return_pressure() + var/total_moles = environment.total_moles() + + if (total_moles) + var/o2_level = environment.oxygen/total_moles + var/n2_level = environment.nitrogen/total_moles + var/co2_level = environment.carbon_dioxide/total_moles + var/plasma_level = environment.toxins/total_moles + var/unknown_level = 1-(o2_level+n2_level+co2_level+plasma_level) + data["aircontents"] = list(\ + "pressure" = "[round(pressure,0.1)]",\ + "nitrogen" = "[round(n2_level*100,0.1)]",\ + "oxygen" = "[round(o2_level*100,0.1)]",\ + "carbon_dioxide" = "[round(co2_level*100,0.1)]",\ + "plasma" = "[round(plasma_level*100,0.01)]",\ + "other" = "[round(unknown_level, 0.01)]",\ + "temp" = "[round(environment.temperature-T0C,0.1)]",\ + "reading" = 1\ + ) + if(isnull(data["aircontents"])) + data["aircontents"] = list("reading" = 0) \ No newline at end of file diff --git a/code/game/objects/items/devices/PDA/messenger.dm b/code/game/objects/items/devices/PDA/messenger.dm new file mode 100644 index 00000000000..56800e19104 --- /dev/null +++ b/code/game/objects/items/devices/PDA/messenger.dm @@ -0,0 +1,283 @@ +/datum/data/pda/app/messenger + name = "Messenger" + icon = "comments-o" + title = "SpaceMessenger V4.0.1" + 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. + +/datum/data/pda/app/messenger/start() + . = ..() + set_new(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["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/obj/item/device/pda/P in PDAs) + 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) + for(var/c in tnote) + if(c["target"] == active_conversation) + data["convo_name"] = sanitize(c["owner"]) + data["convo_job"] = sanitize(c["job"]) + break + + var/list/plugins = list() + if(pda.cartridge) + for(var/datum/data/pda/messenger_plugin/P in pda.cartridge.messenger_plugins) + 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) + + 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 + if("Clear")//Clears messages + if(href_list["option"] == "All") + tnote.Cut() + conversations.Cut() + if(href_list["option"] == "Convo") + var/new_tnote[0] + 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("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 + 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"] + if("Select Conversation") + var/P = href_list["convo"] + for(var/n in conversations) + if(P == n) + active_conversation = P + if("Messenger Plugin") + if(!href_list["target"] || !href_list["plugin"]) + return + + var/obj/item/device/pda/P = locate(href_list["target"]) + if(!P) + usr << "PDA not found." + + var/datum/data/pda/messenger_plugin/plugin = locate(href_list["plugin"]) + 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() + +/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 + if(!t) + return + t = sanitize(copytext(t, 1, MAX_MESSAGE_LEN)) + t = readd_quotes(t) + 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(message_servers) + for (var/obj/machinery/message_server/MS in message_servers) + //PDAs are now dependent on the Message Server. + if(MS.active) + useMS = MS + break + + var/datum/signal/signal = pda.telecomms_process() + + var/useTC = 0 + if(signal) + if(signal.data["done"]) + useTC = 1 + var/turf/pos = get_turf(P) + if(pos.z in signal.data["level"]) + useTC = 2 + //Let's make this barely readable + if(signal.data["compression"] > 0) + t = Gibberish(t, signal.data["compression"] + 50) + + if(useMS && useTC) // only send the message if it's stable + if(useTC != 2) // Does our recipient have a broadcaster on their level? + U << "ERROR: Cannot reach recipient." + return + useMS.send_pda_message("[P.owner]","[pda.owner]","[t]") + tnote.Add(list(list("sent" = 1, "owner" = "[P.owner]", "job" = "[P.ownjob]", "message" = "[t]", "target" = "\ref[P]"))) + PM.tnote.Add(list(list("sent" = 0, "owner" = "[pda.owner]", "job" = "[pda.ownjob]", "message" = "[t]", "target" = "\ref[pda]"))) +/* for(var/mob/M in player_list) + if(M.stat == DEAD && M.client && (M.client.prefs.toggles & CHAT_GHOSTEARS)) // src.client is so that ghosts don't have to listen to mice + if(istype(M, /mob/new_player)) + continue + M.show_message("PDA Message - [owner] -> [P.owner]: [t]") */ + pda.investigate_log("PDA Message - [U.key] - [pda.owner] -> [P.owner]: [t]", "pda") + if(!conversations.Find("\ref[P]")) + conversations.Add("\ref[P]") + if(!PM.conversations.Find("\ref[pda]")) + PM.conversations.Add("\ref[pda]") + +/* + if (prob(15)) //Give the AI a chance of intercepting the message + var/who = src.owner + if(prob(50)) + who = P.owner + for(var/mob/living/silicon/ai/ai in mob_list) + // Allows other AIs to intercept the message but the AI won't intercept their own message. + if(ai.aiPDA != P && ai.aiPDA != src) + ai.show_message("Intercepted message from [who]: [t]") +*/ + + 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) + 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() + var/list/namecounts = list() + + if (toff) + usr << "Turn on your receiver in order to send messages." + return + + for (var/obj/item/device/pda/P in PDAs) + 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 = text("[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 \ No newline at end of file diff --git a/code/game/objects/items/devices/PDA/messenger_plugins.dm b/code/game/objects/items/devices/PDA/messenger_plugins.dm new file mode 100644 index 00000000000..ed4d330fdba --- /dev/null +++ b/code/game/objects/items/devices/PDA/messenger_plugins.dm @@ -0,0 +1,69 @@ +/datum/data/pda/messenger_plugin + var/datum/data/pda/app/messenger/messenger + +/datum/data/pda/messenger_plugin/proc/user_act(mob/user as mob, obj/item/device/pda/P) + + +/datum/data/pda/messenger_plugin/virus + name = "*Send Virus*" + +/datum/data/pda/messenger_plugin/virus/user_act(mob/user as mob, obj/item/device/pda/P) + var/datum/data/pda/app/messenger/M = P.find_program(/datum/data/pda/app/messenger) + + if(M && !M.toff && pda.cartridge.charges > 0) + pda.cartridge.charges-- + return 1 + return 0 + + +/datum/data/pda/messenger_plugin/virus/clown + icon = "star" + +/datum/data/pda/messenger_plugin/virus/clown/user_act(mob/user as mob, obj/item/device/pda/P) + . = ..(user, P) + if(.) + user.show_message("Virus sent!", 1) + P.honkamt = (rand(15,20)) + P.ttone = "honk" + + +/datum/data/pda/messenger_plugin/virus/mime + icon = "arrow-circle-down" + +/datum/data/pda/messenger_plugin/virus/mime/user_act(mob/user as mob, obj/item/device/pda/P) + . = ..(user, P) + if(.) + user.show_message("Virus sent!", 1) + var/datum/data/pda/app/messenger/M = P.find_program(/datum/data/pda/app/messenger) + if(M) + M.silent = 1 + P.ttone = "silence" + + +/datum/data/pda/messenger_plugin/virus/detonate + name = "*Detonate*" + icon = "exclamation-circle" + +/datum/data/pda/messenger_plugin/virus/detonate/user_act(mob/user as mob, obj/item/device/pda/P) + . = ..(user, P) + if(.) + var/difficulty = 0 + + if(pda.cartridge) + difficulty += pda.cartridge.programs.len / 2 + else + difficulty += 2 + + if(prob(difficulty * 12) || (pda.hidden_uplink)) + user.show_message("An error flashes on your [pda].", 1) + else if (prob(difficulty * 3)) + user.show_message("Energy feeds back into your [pda]!", 1) + pda.close(user) + pda.explode() + log_admin("[key_name(user)] just attempted to blow up [P] with the Detomatix cartridge but failed, blowing themselves up") + message_admins("[key_name_admin(user)] just attempted to blow up [P] with the Detomatix cartridge but failed, blowing themselves up", 1) + else + user.show_message("Success!", 1) + log_admin("[key_name(user)] just attempted to blow up [P] with the Detomatix cartridge and succeded") + message_admins("[key_name_admin(user)] just attempted to blow up [P] with the Detomatix cartridge and succeded", 1) + P.explode() \ No newline at end of file diff --git a/code/game/objects/items/devices/PDA/pdas.dm b/code/game/objects/items/devices/PDA/pdas.dm new file mode 100644 index 00000000000..86ca9912e45 --- /dev/null +++ b/code/game/objects/items/devices/PDA/pdas.dm @@ -0,0 +1,193 @@ +/obj/item/device/pda/medical + default_cartridge = /obj/item/weapon/cartridge/medical + icon_state = "pda-medical" + +/obj/item/device/pda/viro + default_cartridge = /obj/item/weapon/cartridge/medical + icon_state = "pda-virology" + +/obj/item/device/pda/engineering + default_cartridge = /obj/item/weapon/cartridge/engineering + icon_state = "pda-engineer" + +/obj/item/device/pda/security + default_cartridge = /obj/item/weapon/cartridge/security + icon_state = "pda-security" + +/obj/item/device/pda/detective + default_cartridge = /obj/item/weapon/cartridge/detective + icon_state = "pda-security" + +/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-janitor" + ttone = "slip" + +/obj/item/device/pda/toxins + default_cartridge = /obj/item/weapon/cartridge/signal/toxins + icon_state = "pda-science" + 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/clown/Crossed(AM as mob|obj) //Clown PDA is slippery. + if (istype(AM, /mob/living/carbon)) + var/mob/living/carbon/M = AM + M.slip("pda", 8, 5, 0, 1) + +/obj/item/device/pda/mime + default_cartridge = /obj/item/weapon/cartridge/mime + icon_state = "pda-mime" + ttone = "silence" + +/obj/item/device/pda/mime/New() + var/datum/data/pda/app/messenger/M = find_program(/datum/data/pda/app/messenger) + if(M) + M.silent = 1 + +/obj/item/device/pda/heads + default_cartridge = /obj/item/weapon/cartridge/head + icon_state = "pda-h" + +/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-captain" + detonate = 0 + //toff = 1 + +/obj/item/device/pda/heads/ntrep + default_cartridge = /obj/item/weapon/cartridge/supervisor + icon_state = "pda-h" + +/obj/item/device/pda/heads/magistrate + default_cartridge = /obj/item/weapon/cartridge/supervisor + icon_state = "pda-h" + +/obj/item/device/pda/heads/blueshield + default_cartridge = /obj/item/weapon/cartridge/hos + icon_state = "pda-h" + +/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-qm" + +/obj/item/device/pda/shaftminer + icon_state = "pda-miner" + +/obj/item/device/pda/syndicate + default_cartridge = /obj/item/weapon/cartridge/syndicate + icon_state = "pda-syndi" + name = "Military PDA" + owner = "John Doe" + +/obj/item/device/pda/syndicate/New() + var/datum/data/pda/app/messenger/M = find_program(/datum/data/pda/app/messenger) + if(M) + M.m_hidden = 1 + +/obj/item/device/pda/chaplain + icon_state = "pda-chaplain" + 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/botanist + icon_state = "pda-hydro" + +/obj/item/device/pda/roboticist + icon_state = "pda-roboticist" + +/obj/item/device/pda/librarian + icon_state = "pda-library" + desc = "A portable microcomputer by Thinktronic Systems, LTD. This is model is a WGW-11 series e-reader." + model_name = "Thinktronic 5290 WGW-11 Series E-reader and Personal Data Assistant" + +/obj/item/device/pda/librarian/New() + var/datum/data/pda/app/messenger/M = find_program(/datum/data/pda/app/messenger) + if(M) + M.silent = 1 //Quiet in the library! + +/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." + model_name = "Thinktronic 5230 Personal Data Assistant Deluxe Special Max Turbo Limited Edition" + +/obj/item/device/pda/chef + icon_state = "pda-chef" + +/obj/item/device/pda/bar + icon_state = "pda-bartender" + +/obj/item/device/pda/atmos + default_cartridge = /obj/item/weapon/cartridge/atmos + icon_state = "pda-atmos" + +/obj/item/device/pda/chemist + default_cartridge = /obj/item/weapon/cartridge/chemistry + icon_state = "pda-chemistry" + +/obj/item/device/pda/geneticist + default_cartridge = /obj/item/weapon/cartridge/medical + icon_state = "pda-genetics" + +/obj/item/device/pda/centcom + default_cartridge = /obj/item/weapon/cartridge/centcom + icon_state = "pda-h" + +//Some spare PDAs in a box +/obj/item/weapon/storage/box/PDAs + name = "spare PDAs" + desc = "A box of spare PDA microcomputers." + icon = 'icons/obj/pda.dmi' + icon_state = "pdabox" + + New() + ..() + new /obj/item/device/pda(src) + new /obj/item/device/pda(src) + new /obj/item/device/pda(src) + new /obj/item/device/pda(src) + new /obj/item/weapon/cartridge/head(src) + + var/newcart = pick( /obj/item/weapon/cartridge/engineering, + /obj/item/weapon/cartridge/security, + /obj/item/weapon/cartridge/medical, + /obj/item/weapon/cartridge/signal/toxins, + /obj/item/weapon/cartridge/quartermaster) + new newcart(src) \ No newline at end of file diff --git a/code/game/objects/items/devices/PDA/radio.dm b/code/game/objects/items/devices/PDA/radio.dm index 3e180a5c700..6a0bba06bdf 100644 --- a/code/game/objects/items/devices/PDA/radio.dm +++ b/code/game/objects/items/devices/PDA/radio.dm @@ -49,8 +49,6 @@ frequency.post_signal(src, signal, filter = s_filter) - return - /obj/item/radio/integrated/receive_signal(datum/signal/signal) /*var/obj/item/device/pda/P = src.loc @@ -79,22 +77,27 @@ if("control") active = locate(href_list["bot"]) - post_signal(control_freq, "command", "bot_status", "active", active, s_filter = bot_filter) + botstatus = list(mode = -1) + spawn(0) + post_signal(control_freq, "command", "bot_status", "active", active, s_filter = bot_filter) if("scanbots") // find all bots botlist = null - post_signal(control_freq, "command", "bot_status", s_filter = bot_filter) + spawn(0) + post_signal(control_freq, "command", "bot_status", s_filter = bot_filter) if("botlist") active = null if("stop", "go") - post_signal(control_freq, "command", href_list["op"], "active", active, s_filter = bot_filter) - post_signal(control_freq, "command", "bot_status", "active", active, s_filter = bot_filter) + spawn(0) + post_signal(control_freq, "command", href_list["op"], "active", active, s_filter = bot_filter) + post_signal(control_freq, "command", "bot_status", "active", active, s_filter = bot_filter) if("summon") - post_signal(control_freq, "command", "summon", "active", active, "target", get_turf(PDA) , "useraccess", PDA.GetAccess(), s_filter = bot_filter) - post_signal(control_freq, "command", "bot_status", "active", active, s_filter = bot_filter) + spawn(0) + post_signal(control_freq, "command", "summon", "active", active, "target", get_turf(PDA) , "useraccess", PDA.GetAccess(), s_filter = bot_filter) + post_signal(control_freq, "command", "bot_status", "active", active, s_filter = bot_filter) /obj/item/radio/integrated/proc/add_to_radio(bot_filter) //Master filter control for bots. Must be placed in the bot's local New() to support map spawned bots. if(radio_controller) @@ -147,13 +150,6 @@ // create/populate lists as they are recvd /obj/item/radio/integrated/mule/receive_signal(datum/signal/signal) -// var/obj/item/device/pda/P = src.loc - - /* - world << "recvd:[P] : [signal.source]" - for(var/d in signal.data) - world << "- [d] = [signal.data[d]]" - */ if(signal.data["type"] == MULE_BOT) if(!botlist) botlist = new() @@ -171,9 +167,6 @@ beacons[signal.data["beacon"] ] = signal.source - -// if(istype(P)) P.updateSelfDialog() - /obj/item/radio/integrated/mule/Topic(href, href_list) //..() //var/obj/item/device/pda/PDA = src.hostpda @@ -182,8 +175,8 @@ cmd = "command [active.suffix]" switch(href_list["op"]) - if("control") + botstatus = list(mode = -1) active = locate(href_list["bot"]) if("scanbots") // find all bots @@ -193,28 +186,37 @@ active = null if("unload") - post_signal(control_freq, cmd, "unload", s_filter = RADIO_MULEBOT) + spawn(0) + post_signal(control_freq, cmd, "unload", s_filter = RADIO_MULEBOT) if("setdest") if(beacons) var/dest = input("Select Bot Destination", "Mulebot [active.suffix] Interlink", active.destination) as null|anything in beacons if(dest) - post_signal(control_freq, cmd, "target", "destination", dest, s_filter = RADIO_MULEBOT) + spawn(0) + post_signal(control_freq, cmd, "target", "destination", dest, s_filter = RADIO_MULEBOT) if("retoff") - post_signal(control_freq, cmd, "autoret", "value", 0, s_filter = RADIO_MULEBOT) + spawn(0) + post_signal(control_freq, cmd, "autoret", "value", 0, s_filter = RADIO_MULEBOT) + if("reton") - post_signal(control_freq, cmd, "autoret", "value", 1, s_filter = RADIO_MULEBOT) + spawn(0) + post_signal(control_freq, cmd, "autoret", "value", 1, s_filter = RADIO_MULEBOT) if("pickoff") - post_signal(control_freq, cmd, "autopick", "value", 0, s_filter = RADIO_MULEBOT) + spawn(0) + post_signal(control_freq, cmd, "autopick", "value", 0, s_filter = RADIO_MULEBOT) if("pickon") - post_signal(control_freq, cmd, "autopick", "value", 1, s_filter = RADIO_MULEBOT) + spawn(0) + post_signal(control_freq, cmd, "autopick", "value", 1, s_filter = RADIO_MULEBOT) if("stop", "go", "home") - post_signal(control_freq, cmd, href_list["op"], s_filter = RADIO_MULEBOT) + spawn(0) + post_signal(control_freq, cmd, href_list["op"], s_filter = RADIO_MULEBOT) - post_signal(control_freq, cmd, "bot_status", s_filter = RADIO_MULEBOT) + spawn(10) + post_signal(control_freq, cmd, "bot_status", s_filter = RADIO_MULEBOT) @@ -262,6 +264,5 @@ signal.encryption = code signal.data["message"] = message - radio_connection.post_signal(src, signal) - - return \ No newline at end of file + spawn(0) + radio_connection.post_signal(src, signal) \ No newline at end of file diff --git a/code/game/objects/items/devices/PDA/utilities.dm b/code/game/objects/items/devices/PDA/utilities.dm new file mode 100644 index 00000000000..bc1b76b2ea6 --- /dev/null +++ b/code/game/objects/items/devices/PDA/utilities.dm @@ -0,0 +1,192 @@ +/datum/data/pda/utility/flashlight + name = "Enable Flashlight" + icon = "lightbulb-o" + + var/fon = 0 //Is the flashlight function on? + var/f_lum = 2 //Luminosity for the flashlight function + +/datum/data/pda/utility/flashlight/start() + fon = !fon + name = fon ? "Disable Flashlight" : "Enable Flashlight" + pda.update_shortcuts() + pda.set_light(fon ? f_lum : 0) + +/datum/data/pda/utility/honk + name = "Honk Synthesizer" + icon = "smile-o" + category = "Clown" + + var/last_honk //Also no honk spamming that's bad too + +/datum/data/pda/utility/honk/start() + if(!(last_honk && world.time < last_honk + 20)) + playsound(pda.loc, 'sound/items/bikehorn.ogg', 50, 1) + last_honk = world.time + +/datum/data/pda/utility/toggle_door + name = "Toggle Door" + icon = "external-link" + var/remote_door_id = "" + +/datum/data/pda/utility/toggle_door/start() + for(var/obj/machinery/door/poddoor/M in world) + if(M.id_tag == remote_door_id) + if(M.density) + M.open() + else + M.close() + +/datum/data/pda/utility/scanmode/medical + base_name = "Med Scanner" + icon = "heart-o" + +/datum/data/pda/utility/scanmode/medical/scan_mob(mob/living/C as mob, mob/living/user as mob) + for (var/mob/O in viewers(C, null)) + O.show_message("[user] has analyzed [C]'s vitals!", 1) + + user.show_message("Analyzing Results for [C]:") + user.show_message("\t Overall Status: [C.stat > 1 ? "dead" : "[C.health - C.halloss]% healthy"]", 1) + user.show_message("\t Damage Specifics: [C.getOxyLoss() > 50 ? "" : ""][C.getOxyLoss()]-[C.getToxLoss() > 50 ? "" : ""][C.getToxLoss()]-[C.getFireLoss() > 50 ? "" : ""][C.getFireLoss()]-[C.getBruteLoss() > 50 ? "" : ""][C.getBruteLoss()]", 1) + user.show_message("\t Key: Suffocation/Toxin/Burns/Brute", 1) + user.show_message("\t Body Temperature: [C.bodytemperature-T0C]°C ([C.bodytemperature*1.8-459.67]°F)", 1) + if(C.timeofdeath && (C.stat == DEAD || (C.status_flags & FAKEDEATH))) + user.show_message("\t Time of Death: [C.timeofdeath]") + if(istype(C, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = C + var/list/damaged = H.get_damaged_organs(1,1) + user.show_message("Localized Damage, Brute/Burn:",1) + if(length(damaged)>0) + for(var/obj/item/organ/external/org in damaged) + user.show_message("\t [capitalize(org.name)]: [org.brute_dam > 0 ? "[org.brute_dam]" : "0"]-[org.burn_dam > 0 ? "[org.burn_dam]" : "0"]", 1) + else + user.show_message("\t Limbs are OK.",1) + +/datum/data/pda/utility/scanmode/dna + base_name = "DNA Scanner" + icon = "link" + +/datum/data/pda/utility/scanmode/dna/scan_mob(mob/living/C as mob, mob/living/user as mob) + if (!istype(C:dna, /datum/dna)) + user << "No fingerprints found on [C]" + else + user << "[C]'s Fingerprints: [md5(C:dna.uni_identity)]" + if (!C:blood_DNA) + user << "No blood found on [C]" + if(C:blood_DNA) + qdel(C:blood_DNA) + else + user << "Blood found on [C]. Analysing..." + spawn(15) + for(var/blood in C:blood_DNA) + user << "Blood type: [C:blood_DNA[blood]]\nDNA: [blood]" + +/datum/data/pda/utility/scanmode/halogen + base_name = "Halogen Counter" + icon = "exclamation-circle" + +/datum/data/pda/utility/scanmode/halogen/scan_mob(mob/living/C as mob, mob/living/user as mob) + for (var/mob/O in viewers(C, null)) + O.show_message("[user] has analyzed [C]'s radiation levels!", 1) + + user.show_message("Analyzing Results for [C]:") + if(C.radiation) + user.show_message("Radiation Level: [C.radiation > 0 ? "[C.radiation]" : "0"]") + else + user.show_message("No radiation detected.") + +/datum/data/pda/utility/scanmode/reagent + base_name = "Reagent Scanner" + icon = "flask" + +/datum/data/pda/utility/scanmode/reagent/scan_atom(atom/A as mob|obj|turf|area, mob/user as mob) + if(!isnull(A.reagents)) + if(A.reagents.reagent_list.len > 0) + var/reagents_length = A.reagents.reagent_list.len + user << "[reagents_length] chemical agent[reagents_length > 1 ? "s" : ""] found." + for (var/re in A.reagents.reagent_list) + user << "\t [re]" + else + user << "No active chemical agents found in [A]." + else + user << "No significant chemical agents found in [A]." + +/datum/data/pda/utility/scanmode/gas + base_name = "Gas Scanner" + icon = "tachometer" + +/datum/data/pda/utility/scanmode/gas/scan_atom(atom/A as mob|obj|turf|area, mob/user as mob) + if (istype(A, /obj/item/weapon/tank)) + var/obj/item/weapon/tank/T = A + pda.atmosanalyzer_scan(T.air_contents, user, T) + else if (istype(A, /obj/machinery/portable_atmospherics)) + var/obj/machinery/portable_atmospherics/T = A + pda.atmosanalyzer_scan(T.air_contents, user, T) + else if (istype(A, /obj/machinery/atmospherics/pipe)) + var/obj/machinery/atmospherics/pipe/T = A + pda.atmosanalyzer_scan(T.parent.air, user, T) + else if (istype(A, /obj/machinery/power/rad_collector)) + var/obj/machinery/power/rad_collector/T = A + if(T.P) + pda.atmosanalyzer_scan(T.P.air_contents, user, T) + else if (istype(A, /obj/item/weapon/flamethrower)) + var/obj/item/weapon/flamethrower/T = A + if(T.ptank) + pda.atmosanalyzer_scan(T.ptank.air_contents, user, T) + else if (istype(A, /obj/machinery/portable_atmospherics/scrubber/huge)) + var/obj/machinery/portable_atmospherics/scrubber/huge/T = A + pda.atmosanalyzer_scan(T.air_contents, user, T) + else if (istype(A, /obj/machinery/atmospherics/unary/tank)) + var/obj/machinery/atmospherics/unary/tank/T = A + pda.atmosanalyzer_scan(T.air_contents, user, T) + +/datum/data/pda/utility/scanmode/notes + base_name = "Note Scanner" + icon = "clipboard" + var/datum/data/pda/app/notekeeper/notes + +/datum/data/pda/utility/scanmode/notes/start() + . = ..() + notes = pda.find_program(/datum/data/pda/app/notekeeper) + +/datum/data/pda/utility/scanmode/notes/scan_atom(atom/A as mob|obj|turf|area, mob/user as mob) + if(notes && istype(A, /obj/item/weapon/paper)) + var/obj/item/weapon/paper/P = A + + // JMO 20140705: Makes scanned document show up properly in the notes. Not pretty for formatted documents, + // as this will clobber the HTML, but at least it lets you scan a document. You can restore the original + // notes by editing the note again. (Was going to allow you to edit, but scanned documents are too long.) + var/raw_scan = P.info + var/formatted_scan = "" + // Scrub out the tags (replacing a few formatting ones along the way) + // Find the beginning and end of the first tag. + var/tag_start = findtext(raw_scan, "<") + var/tag_stop = findtext(raw_scan, ">") + // Until we run out of complete tags... + while(tag_start && tag_stop) + var/pre = copytext(raw_scan, 1, tag_start) // Get the stuff that comes before the tag + var/tag = lowertext(copytext(raw_scan, tag_start + 1, tag_stop)) // Get the tag so we can do intellegent replacement + var/tagend = findtext(tag, " ") // Find the first space in the tag if there is one. + // Anything that's before the tag can just be added as is. + formatted_scan = formatted_scan + pre + // If we have a space after the tag (and presumably attributes) just crop that off. + if(tagend) + tag = copytext(tag, 1, tagend) + if(tag == "p" || tag == "/p" || tag == "br") // Check if it's I vertical space tag. + formatted_scan = formatted_scan + "
" // If so, add some padding in. + raw_scan = copytext(raw_scan, tag_stop + 1) // continue on with the stuff after the tag + // Look for the next tag in what's left + tag_start = findtext(raw_scan, "<") + tag_stop = findtext(raw_scan, ">") + // Anything that is left in the page. just tack it on to the end as is + formatted_scan = formatted_scan + raw_scan + // If there is something in there already, pad it out. + if(length(notes.note) > 0) + notes.note = notes.note + "

" + // Store the scanned document to the notes + notes.note = "Scanned Document. Edit to restore previous notes/delete scan.
----------
" + formatted_scan + "
" + // notehtml ISN'T set to allow user to get their old notes back. A better implementation would add a "scanned documents" + // feature to the PDA, which would better convey the availability of the feature, but this will work for now. + // Inform the user + user << "Paper scanned and OCRed to notekeeper." //concept of scanning paper copyright brainoblivion 2009 + else + user << "Error scanning [A]." \ No newline at end of file diff --git a/code/modules/events/money_spam.dm b/code/modules/events/money_spam.dm index 2bafc9f3cc9..37a29a00bbd 100644 --- a/code/modules/events/money_spam.dm +++ b/code/modules/events/money_spam.dm @@ -27,16 +27,18 @@ if(useMS) if(prob(5)) // /obj/machinery/message_server/proc/send_pda_message(var/recipient = "",var/sender = "",var/message = "") - var/obj/item/device/pda/P var/list/viables = list() for(var/obj/item/device/pda/check_pda in PDAs) - if (!check_pda.owner||check_pda.toff||check_pda == src||check_pda.hidden) + var/datum/data/pda/app/messenger/check_m = check_pda.find_program(/datum/data/pda/app/messenger) + + if (!check_m || !check_m.can_receive()) continue viables.Add(check_pda) if(!viables.len) return - P = pick(viables) + var/obj/item/device/pda/P = pick(viables) + var/datum/data/pda/app/messenger/PM = P.find_program(/datum/data/pda/app/messenger) var/sender var/message @@ -104,7 +106,7 @@ //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]
" - P.play_ringtone() + PM.play_ringtone() //Search for holder of the PDA. var/mob/living/L = null if(P.loc && isliving(P.loc)) diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm index 2fd2ddcab61..420b897626b 100644 --- a/code/modules/mob/living/silicon/pai/pai.dm +++ b/code/modules/mob/living/silicon/pai/pai.dm @@ -108,7 +108,8 @@ pda.ownjob = "Personal Assistant" pda.owner = text("[]", src) pda.name = pda.owner + " (" + pda.ownjob + ")" - pda.toff = 1 + var/datum/data/pda/app/messenger/M = pda.find_program(/datum/data/pda/app/messenger) + M.toff = 1 ..() /mob/living/silicon/pai/Login() diff --git a/code/modules/mob/living/silicon/pai/software_modules.dm b/code/modules/mob/living/silicon/pai/software_modules.dm index 11e3abaf7e8..5278300ffb5 100644 --- a/code/modules/mob/living/silicon/pai/software_modules.dm +++ b/code/modules/mob/living/silicon/pai/software_modules.dm @@ -142,15 +142,24 @@ on_ui_interact(mob/living/silicon/pai/user, datum/nanoui/ui=null, force_open=1) var/data[0] - data["receiver_off"] = user.pda.toff - data["ringer_off"] = user.pda.silent + if(!user.pda) + return + var/datum/data/pda/app/messenger/M = user.pda.find_program(/datum/data/pda/app/messenger) + if(!M) + return + + data["receiver_off"] = M.toff + data["ringer_off"] = M.silent data["current_ref"] = null data["current_name"] = user.current_pda_messaging var/pdas[0] - if(!user.pda.toff) + if(!M.toff) for(var/obj/item/device/pda/P in PDAs) - if(!P.owner || P.toff || P == user.pda || P.hidden) continue + var/datum/data/pda/app/messenger/PM = P.find_program(/datum/data/pda/app/messenger) + + if(P == user.pda || !PM || !PM.can_receive()) + continue var/pda[0] pda["name"] = "[P]" pda["owner"] = "[P.owner]" @@ -163,7 +172,7 @@ var/messages[0] if(user.current_pda_messaging) - for(var/index in user.pda.tnote) + for(var/index in M.tnote) if(index["owner"] != user.current_pda_messaging) continue var/msg[0] @@ -188,11 +197,15 @@ if(!istype(P)) return if(!isnull(P.pda)) + var/datum/data/pda/app/messenger/M = P.pda.find_program(/datum/data/pda/app/messenger) + if(!M) + return + if(href_list["toggler"]) - P.pda.toff = href_list["toggler"] != "1" + M.toff = href_list["toggler"] != "1" return 1 else if(href_list["ringer"]) - P.pda.silent = href_list["ringer"] != "1" + M.silent = href_list["ringer"] != "1" return 1 else if(href_list["select"]) var/s = href_list["select"] @@ -206,7 +219,7 @@ return alert("Communications circuits remain uninitialized.") var/target = locate(href_list["target"]) - P.pda.create_message(P, target, 1) + M.create_message(P, target, 1) return 1 /datum/pai_software/med_records diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 3f56a1bfc25..2d6b918983c 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -174,7 +174,9 @@ var/list/robot_verbs_default = list( rbPDA = new/obj/item/device/pda/ai(src) rbPDA.set_name_and_job(custom_name,braintype) if(scrambledcodes) - rbPDA.hidden = 1 + var/datum/data/pda/app/messenger/M = rbPDA.find_program(/datum/data/pda/app/messenger) + if(M) + M.hidden = 1 /mob/living/silicon/robot/binarycheck() if(is_component_functioning("comms")) diff --git a/code/modules/ninja/suit/SpiderOS.dm b/code/modules/ninja/suit/SpiderOS.dm index de7cc2e179c..11a595e6645 100644 --- a/code/modules/ninja/suit/SpiderOS.dm +++ b/code/modules/ninja/suit/SpiderOS.dm @@ -231,8 +231,8 @@ if(L) L << "\icon[P] Message from unknown source: \"[t]\" (Unable to Reply)" P.play_ringtone() - P.overlays.Cut() - P.overlays += image('icons/obj/pda.dmi', "pda-r") + var/datum/data/pda/app/messenger/M = P.find_program(/datum/data/pda/app/messenger) + M.set_new(1) 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/nano/assets/nano.js b/nano/assets/nano.js index 9ae1ecc460a..1af5aed8ad1 100644 --- a/nano/assets/nano.js +++ b/nano/assets/nano.js @@ -1 +1 @@ -function NanoStateDefaultClass(){this.key="default",this.key=this.key.toLowerCase(),NanoStateManager.addState(this)}function NanoStateClass(){}var NanoUtility=function(){var e={};return{init:function(){var t=$("body");e=t.data("urlParameters")},generateHref:function(t){var n="?";for(var a in e)e.hasOwnProperty(a)&&("?"!==n&&(n+=";"),n+=a+"="+e[a]);for(var a in t)t.hasOwnProperty(a)&&("?"!==n&&(n+=";"),n+=a+"="+t[a]);return n},winset:function(e,t,n){var a,r;return null==n&&(n=NanoStateManager.getData().config.window.ref),a={},a[n+"."+e]=t,r=a,location.href=NanoUtility.href("winset",r)},extend:function(e,t){return Object.keys(t).forEach(function(n){var a;return a=t[n],a&&"[object Object]"===Object.prototype.toString.call(a)?(e[n]=e[n]||{},NanoUtility.extend(e[n],a)):e[n]=a}),e},href:function(e,t){return null==e&&(e=""),null==t&&(t={}),e=new Url("byond://"+e),NanoUtility.extend(e.query,t),e},close:function(){var t;return t={command:"nanoclose "+e.src},this.winset("is-visible","false"),location.href=NanoUtility.href("winset",t)}}}();"undefined"==typeof jQuery&&reportError("ERROR: Javascript library failed to load!"),"undefined"==typeof doT&&reportError("ERROR: Template engine failed to load!");var reportError=function(e){window.location="byond://?nano_err="+encodeURIComponent(e),alert(e)};$(document).ready(function(){NanoUtility.init(),NanoStateManager.init(),NanoTemplate.init(),NanoWindow.init()}),Array.prototype.indexOf||(Array.prototype.indexOf=function(e){var t=this.length,n=Number(arguments[1])||0;for(n=0>n?Math.ceil(n):Math.floor(n),0>n&&(n+=t);t>n;n++)if(n in this&&this[n]===e)return n;return-1}),String.prototype.format||(String.prototype.format=function(e){var t=this;return t.replace(String.prototype.format.regex,function(t){var n,a=parseInt(t.substring(1,t.length-1));return n=a>=0?e[a]:-1===a?"{":-2===a?"}":""})},String.prototype.format.regex=new RegExp("{-?[0-9]+}","g")),Object.size=function(e){var t,n=0;for(var t in e)e.hasOwnProperty(t)&&n++;return n},window.console||(window.console={log:function(e){return!1}}),String.prototype.toTitleCase=function(){var e=/^(a|an|and|as|at|but|by|en|for|if|in|of|on|or|the|to|vs?\.?|via)$/i;return this.replace(/([^\W_]+[^\s-]*) */g,function(t,n,a,r){return a>0&&a+n.length!==r.length&&n.search(e)>-1&&":"!==r.charAt(a-2)&&r.charAt(a-1).search(/[^\s-]/)<0?t.toLowerCase():n.substr(1).search(/[A-Z]|\../)>-1?t:t.charAt(0).toUpperCase()+t.substr(1)})},$.ajaxSetup({cache:!1}),Function.prototype.inheritsFrom=function(e){return this.prototype=new e,this.prototype.constructor=this,this.prototype.parent=e.prototype,this},String.prototype.trim||(String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,"")}),String.prototype.ckey||(String.prototype.ckey=function(){return this.replace(/\W/g,"").toLowerCase()}),NanoStateManager=function(){var e=!1,t=null,n={},a={},r={},o=null,i=function(){t=$("body").data("initialData"),null!=t&&t.hasOwnProperty("config")&&t.hasOwnProperty("data")||reportError("Error: Initial data did not load correctly.");var n="default";t.config.hasOwnProperty("stateKey")&&t.config.stateKey&&(n=t.config.stateKey.toLowerCase()),NanoStateManager.setCurrentState(n),$(document).on("templatesLoaded",function(){l(t),e=!0})},s=function(n){var a;try{a=jQuery.parseJSON(n)}catch(r){return void reportError("recieveUpdateData failed.
Error name: "+r.name+"
Error Message: "+r.message)}a.hasOwnProperty("data")||(t&&t.hasOwnProperty("data")?a.data=t.data:a.data={}),e?l(a):t=a},l=function(e){if(null!=o){if(e=o.onBeforeUpdate(e),e===!1)return void reportError("data is false, return");t=e,o.onUpdate(t),o.onAfterUpdate(t)}},c=function(e,t){for(var n in e)e.hasOwnProperty(n)&&jQuery.isFunction(e[n])&&(t=e[n].call(this,t));return t};return{init:function(){i()},receiveUpdateData:function(e){s(e)},addBeforeUpdateCallback:function(e,t){n[e]=t},addBeforeUpdateCallbacks:function(e){for(var t in e)e.hasOwnProperty(t)&&NanoStateManager.addBeforeUpdateCallback(t,e[t])},removeBeforeUpdateCallback:function(e){n.hasOwnProperty(e)&&delete n[e]},executeBeforeUpdateCallbacks:function(e){return c(n,e)},addAfterUpdateCallback:function(e,t){a[e]=t},addAfterUpdateCallbacks:function(e){for(var t in e)e.hasOwnProperty(t)&&NanoStateManager.addAfterUpdateCallback(t,e[t])},removeAfterUpdateCallback:function(e){a.hasOwnProperty(e)&&delete a[e]},executeAfterUpdateCallbacks:function(e){return c(a,e)},addState:function(e){return e instanceof NanoStateClass?e.key?void(r[e.key]=e):void reportError("ERROR: Attempted to add a state with an invalid stateKey"):void reportError("ERROR: Attempted to add a state which is not instanceof NanoStateClass")},setCurrentState:function(e){if("undefined"==typeof e||!e)return reportError("ERROR: No state key was passed!"),!1;if(!r.hasOwnProperty(e))return reportError("ERROR: Attempted to set a current state which does not exist: "+e),!1;var t=o;return o=r[e],null!=t&&t.onRemove(o),o.onAdd(t),!0},getCurrentState:function(){return o},getData:function(){return t}}}(),NanoBaseCallbacks=function(){var e=!0,t={},n={status:function(t){var n;return 2==t.config.status?(n="good",$(".linkActive").removeClass("inactive")):1==t.config.status?(n="average",$(".linkActive").addClass("inactive")):(n="bad",$(".linkActive").addClass("inactive")),$(".statusicon").removeClass("good bad average").addClass(n),$(".linkActive").stopTime("linkPending"),$(".linkActive").removeClass("linkPending"),$(".linkActive").off("click").on("click",function(n){n.preventDefault();var a=$(this).data("href");null!=a&&e&&(e=!1,$("body").oneTime(300,"enableClick",function(){e=!0}),2==t.config.status&&$(this).oneTime(300,"linkPending",function(){$(this).addClass("linkPending")}),window.location.href=a)}),t},nanomap:function(e){return $(".mapIcon").off("mouseenter mouseleave").on("mouseenter",function(e){$("#uiMapTooltip").html($(this).children(".tooltip").html()).show().stopTime().oneTime(5e3,"hideTooltip",function(){$(this).fadeOut(500)})}),$(".zoomLink").off("click").on("click",function(e){e.preventDefault();var t=$(this).data("zoomLevel"),n=$("#uiMap"),a=n.width()*t,r=n.height()*t;n.css({zoom:t,left:"50%",top:"50%",marginLeft:"-"+Math.floor(a/2)+"px",marginTop:"-"+Math.floor(r/2)+"px"})}),$("#uiMapImage").attr("src","nanomap_z"+e.config.mapZLevel+".png"),e}};return{addCallbacks:function(){NanoStateManager.addBeforeUpdateCallbacks(t),NanoStateManager.addAfterUpdateCallbacks(n)},removeCallbacks:function(){for(var e in t)t.hasOwnProperty(e)&&NanoStateManager.removeBeforeUpdateCallback(e);for(var e in n)n.hasOwnProperty(e)&&NanoStateManager.removeAfterUpdateCallback(e)}}}(),NanoBaseHelpers=function(){var e={syndicateMode:function(){return $("body").css("background-color","#8f1414"),$("body").css("background-image","url('uiBackground-Syndicate.png')"),$("body").css("background-position","50% 0"),$("body").css("background-repeat","repeat-x"),$("#uiTitleFluff").css("background-image","url('uiTitleFluff-Syndicate.png')"),$("#uiTitleFluff").css("background-position","50% 50%"),$("#uiTitleFluff").css("background-repeat","no-repeat"),""},combine:function(e,t){return e&&t?e.concat(t):e||t},dump:function(e){return JSON.stringify(e)},link:function(e,t,n,a,r,o){var i="",s="noIcon";"undefined"!=typeof t&&t&&(i='
',s="hasIcon"),"undefined"!=typeof r&&r||(r="link");var l="";return"undefined"!=typeof o&&o&&(l='id="'+o+'"'),"undefined"!=typeof a&&a?'":'
"+i+e+"
"},xor:function(e,t){return e^t},precisionRound:function(e,t){if(0==t)return Math.round(number);var n=Math.pow(10,t);return Math.round(e*n)/n},round:function(e){return Math.round(e)},fixed:function(e){return Math.round(10*e)/10},floor:function(e){return Math.floor(e)},ceil:function(e){return Math.ceil(e)},string:function(){if(0==arguments.length)return"";if(1==arguments.length)return arguments[0];if(arguments.length>1){stringArgs=[];for(var e=1;et?t>e?e=t:e>n&&(e=n):e>t?e=t:n>e&&(e=n),"undefined"!=typeof a&&a||(a=""),"undefined"!=typeof r&&r||(r="");var o=Math.round((e-t)/(n-t)*100);return'
'+r+"
"},dangerToClass:function(e){return 0==e?"good":1==e?"average":"bad"},dangerToSpan:function(e){return 0==e?'"Good"':1==e?'"Minor Alert"':'"Major Alert"'},generateHref:function(e){var t=$("body");_urlParameters=t.data("urlParameters");var n="?";for(var a in _urlParameters)_urlParameters.hasOwnProperty(a)&&("?"!==n&&(n+=";"),n+=a+"="+_urlParameters[a]);for(var a in e)e.hasOwnProperty(a)&&("?"!==n&&(n+=";"),n+=a+"="+e[a]);return n},displayDNABlocks:function(e,t,n,a,r){if(!e)return'
Please place a valid subject into the DNA modifier.
';var o=e.split(""),i='
',s=1,l=1;for(var c in o)if(o.hasOwnProperty(c)&&"object"!=typeof o[c]){var u;u="UI"==r.toUpperCase()?{selectUIBlock:s,selectUISubblock:l}:{selectSEBlock:s,selectSESubblock:l};var d="linkActive";s==t&&l==n&&(d="selected"),i+='",c++,c%a==0&&c
"):l++}return i+="
"},cMirror:function(e){CodeMirror.fromTextArea(document.getElementById(e),{lineNumbers:!0,indentUnit:4,indentWithTabs:!0,theme:"lesser-dark"})}};return{addHelpers:function(){NanoTemplate.addHelpers(e)},removeHelpers:function(){for(var t in e)e.hasOwnProperty(t)&&NanoTemplate.removeHelper(t)}}}(),NanoStateDefaultClass.inheritsFrom(NanoStateClass);var NanoStateDefault=new NanoStateDefaultClass;NanoStateClass.prototype.key=null,NanoStateClass.prototype.layoutRendered=!1,NanoStateClass.prototype.contentRendered=!1,NanoStateClass.prototype.mapInitialised=!1,NanoStateClass.prototype.isCurrent=function(){return NanoStateManager.getCurrentState()==this},NanoStateClass.prototype.onAdd=function(e){NanoBaseCallbacks.addCallbacks(),NanoBaseHelpers.addHelpers()},NanoStateClass.prototype.onRemove=function(e){NanoBaseCallbacks.removeCallbacks(),NanoBaseHelpers.removeHelpers()},NanoStateClass.prototype.onBeforeUpdate=function(e){return e=NanoStateManager.executeBeforeUpdateCallbacks(e)},NanoStateClass.prototype.onUpdate=function(e){try{(!this.layoutRendered||e.config.hasOwnProperty("autoUpdateLayout")&&e.config.autoUpdateLayout)&&($("#uiLayout").html(NanoTemplate.parse("layout",e)),this.layoutRendered=!0),(!this.contentRendered||e.config.hasOwnProperty("autoUpdateContent")&&e.config.autoUpdateContent)&&($("#uiContent").html(NanoTemplate.parse("main",e)),this.contentRendered=!0),NanoTemplate.templateExists("mapContent")&&(this.mapInitialised||($("#uiMap").draggable(),$("#uiMapTooltip").off("click").on("click",function(e){e.preventDefault(),$(this).fadeOut(400)}),this.mapInitialised=!0),$("#uiMapContent").html(NanoTemplate.parse("mapContent",e)),e.config.hasOwnProperty("showMap")&&e.config.showMap?($("#uiContent").addClass("hidden"),$("#uiMapWrapper").removeClass("hidden")):($("#uiMapWrapper").addClass("hidden"),$("#uiContent").removeClass("hidden"))),NanoTemplate.templateExists("mapHeader")&&$("#uiMapHeader").html(NanoTemplate.parse("mapHeader",e)),NanoTemplate.templateExists("mapFooter")&&$("#uiMapFooter").html(NanoTemplate.parse("mapFooter",e))}catch(t){return void reportError("ERROR: An error occurred while rendering the UI: "+t.message)}},NanoStateClass.prototype.onAfterUpdate=function(e){NanoStateManager.executeAfterUpdateCallbacks(e)},NanoStateClass.prototype.alertText=function(e){alert(e)};var NanoTemplate=function(){var e={},t={},n={},a={},r=function(){e=$("body").data("templateData"),null==e&&reportError("Error: Template data did not load correctly."),o()},o=function(){var t=Object.size(e);if(!t)return void $(document).trigger("templatesLoaded");for(var n in e)if(e.hasOwnProperty(n))return void $.when($.ajax({url:e[n],cache:!1,dataType:"text"})).done(function(t){t+='
';try{NanoTemplate.addTemplate(n,t)}catch(a){return void reportError("ERROR: An error occurred while loading the UI: "+a.message)}delete e[n],o()}).fail(function(){reportError("ERROR: Loading template "+n+"("+e[n]+") failed!")})},i=function(){for(var e in t)try{n[e]=doT.template(t[e],null,t)}catch(a){reportError(a.message)}};return{init:function(){r()},addTemplate:function(e,n){t[e]=n},templateExists:function(e){return t.hasOwnProperty(e)},parse:function(e,r){if(!n.hasOwnProperty(e)||!n[e]){if(!t.hasOwnProperty(e))return reportError('ERROR: Template "'+e+'" does not exist in _compiledTemplates!'),"

Template error (does not exist)

";i()}return"function"!=typeof n[e]?(reportError(n[e]),reportError('ERROR: Template "'+e+'" failed to compile!'),"

Template error (failed to compile)

"):n[e].call(this,r.data,r.config,a)},addHelper:function(e,t){return jQuery.isFunction(t)?void(a[e]=t):void reportError("NanoTemplate.addHelper failed to add "+e+" as it is not a function.")},addHelpers:function(e){for(var t in e)e.hasOwnProperty(t)&&NanoTemplate.addHelper(t,e[t])},removeHelper:function(e){helpers.hasOwnProperty(e)&&delete a[e]}}}(),NanoWindow=function(){var e,t,n,a,r,o,i=function(e,t){NanoUtility.winset("pos",e+","+t)},s=function(e,t){NanoUtility.winset("size",e+","+t)},l=function(){NanoStateManager.getData().config.user.fancy&&(c(),u(),d(),f())},c=function(){NanoUtility.winset("titlebar",0),NanoUtility.winset("can-resize",0),$(".fancy").show(),$("#uiTitleFluff").css("right","65px")},u=function(){var e=function(){return NanoUtility.close()},t=function(){return NanoUtility.winset("is-minimized","true")};$(".close").on("click",function(t){e()}),$(".minimize").on("click",function(e){t()})},d=function(){$("#uiTitleWrapper").on("mousemove",function(e){p()}),$("#uiTitleWrapper").on("mousedown",function(t){e=!0}),$("#uiTitleWrapper").on("mouseup",function(a){e=!1,t=null,n=null})},p=function(a){var r,o;null==a&&(a=window.event),e&&(null==t&&(t=a.screenX),null==n&&(n=a.screenY),r=a.screenX-t+window.screenLeft,o=a.screenY-n+window.screenTop,i(r,o),t=a.screenX,n=a.screenY)},f=function(){$("#resize").on("mousemove",function(e){m()}),$("#resize").on("mousedown",function(e){a=!0}),$("#resize").on("mouseup",function(e){a=!1})},m=function(){var e,t;null==event&&(event=window.event),a&&(null==r&&(r=event.screenX),null==o&&(o=event.screenY),e=Math.max(150,event.screenX-r+window.innerWidth),t=Math.max(150,event.screenY-o+window.innerHeight),s(e,t),r=event.screenX,o=event.screenY)};return{init:function(){$(document).on("templatesLoaded",function(){l()})}}}(); \ No newline at end of file +function NanoStateDefaultClass(){this.key="default",this.key=this.key.toLowerCase(),NanoStateManager.addState(this)}function NanoStatePDAClass(){this.key="pda",this.key=this.key.toLowerCase(),NanoStateManager.addState(this)}function NanoStateClass(){}var NanoUtility=function(){var e={};return{init:function(){var t=$("body");e=t.data("urlParameters")},generateHref:function(t){var n="?";for(var a in e)e.hasOwnProperty(a)&&("?"!==n&&(n+=";"),n+=a+"="+e[a]);for(var a in t)t.hasOwnProperty(a)&&("?"!==n&&(n+=";"),n+=a+"="+t[a]);return n},winset:function(e,t,n){var a,r;return null==n&&(n=NanoStateManager.getData().config.window.ref),a={},a[n+"."+e]=t,r=a,location.href=NanoUtility.href("winset",r)},extend:function(e,t){return Object.keys(t).forEach(function(n){var a;return a=t[n],a&&"[object Object]"===Object.prototype.toString.call(a)?(e[n]=e[n]||{},NanoUtility.extend(e[n],a)):e[n]=a}),e},href:function(e,t){return null==e&&(e=""),null==t&&(t={}),e=new Url("byond://"+e),NanoUtility.extend(e.query,t),e},close:function(){var t;return t={command:"nanoclose "+e.src},this.winset("is-visible","false"),location.href=NanoUtility.href("winset",t)}}}();"undefined"==typeof jQuery&&reportError("ERROR: Javascript library failed to load!"),"undefined"==typeof doT&&reportError("ERROR: Template engine failed to load!");var reportError=function(e){window.location="byond://?nano_err="+encodeURIComponent(e),alert(e)};$(document).ready(function(){NanoUtility.init(),NanoStateManager.init(),NanoTemplate.init(),NanoWindow.init()}),Array.prototype.indexOf||(Array.prototype.indexOf=function(e){var t=this.length,n=Number(arguments[1])||0;for(n=0>n?Math.ceil(n):Math.floor(n),0>n&&(n+=t);t>n;n++)if(n in this&&this[n]===e)return n;return-1}),String.prototype.format||(String.prototype.format=function(e){var t=this;return t.replace(String.prototype.format.regex,function(t){var n,a=parseInt(t.substring(1,t.length-1));return n=a>=0?e[a]:-1===a?"{":-2===a?"}":""})},String.prototype.format.regex=new RegExp("{-?[0-9]+}","g")),Object.size=function(e){var t,n=0;for(var t in e)e.hasOwnProperty(t)&&n++;return n},window.console||(window.console={log:function(e){return!1}}),String.prototype.toTitleCase=function(){var e=/^(a|an|and|as|at|but|by|en|for|if|in|of|on|or|the|to|vs?\.?|via)$/i;return this.replace(/([^\W_]+[^\s-]*) */g,function(t,n,a,r){return a>0&&a+n.length!==r.length&&n.search(e)>-1&&":"!==r.charAt(a-2)&&r.charAt(a-1).search(/[^\s-]/)<0?t.toLowerCase():n.substr(1).search(/[A-Z]|\../)>-1?t:t.charAt(0).toUpperCase()+t.substr(1)})},$.ajaxSetup({cache:!1}),Function.prototype.inheritsFrom=function(e){return this.prototype=new e,this.prototype.constructor=this,this.prototype.parent=e.prototype,this},String.prototype.trim||(String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,"")}),String.prototype.ckey||(String.prototype.ckey=function(){return this.replace(/\W/g,"").toLowerCase()}),NanoStateManager=function(){var e=!1,t=null,n={},a={},r={},o=null,i=function(){t=$("body").data("initialData"),null!=t&&t.hasOwnProperty("config")&&t.hasOwnProperty("data")||reportError("Error: Initial data did not load correctly.");var n="default";t.config.hasOwnProperty("stateKey")&&t.config.stateKey&&(n=t.config.stateKey.toLowerCase()),NanoStateManager.setCurrentState(n),$(document).on("templatesLoaded",function(){l(t),e=!0})},s=function(n){var a;try{a=jQuery.parseJSON(n)}catch(r){return void reportError("recieveUpdateData failed.
Error name: "+r.name+"
Error Message: "+r.message)}a.hasOwnProperty("data")||(t&&t.hasOwnProperty("data")?a.data=t.data:a.data={}),e?l(a):t=a},l=function(e){if(null!=o){if(e=o.onBeforeUpdate(e),e===!1)return void reportError("data is false, return");t=e,o.onUpdate(t),o.onAfterUpdate(t)}},c=function(e,t){for(var n in e)e.hasOwnProperty(n)&&jQuery.isFunction(e[n])&&(t=e[n].call(this,t));return t};return{init:function(){i()},receiveUpdateData:function(e){s(e)},addBeforeUpdateCallback:function(e,t){n[e]=t},addBeforeUpdateCallbacks:function(e){for(var t in e)e.hasOwnProperty(t)&&NanoStateManager.addBeforeUpdateCallback(t,e[t])},removeBeforeUpdateCallback:function(e){n.hasOwnProperty(e)&&delete n[e]},executeBeforeUpdateCallbacks:function(e){return c(n,e)},addAfterUpdateCallback:function(e,t){a[e]=t},addAfterUpdateCallbacks:function(e){for(var t in e)e.hasOwnProperty(t)&&NanoStateManager.addAfterUpdateCallback(t,e[t])},removeAfterUpdateCallback:function(e){a.hasOwnProperty(e)&&delete a[e]},executeAfterUpdateCallbacks:function(e){return c(a,e)},addState:function(e){return e instanceof NanoStateClass?e.key?void(r[e.key]=e):void reportError("ERROR: Attempted to add a state with an invalid stateKey"):void reportError("ERROR: Attempted to add a state which is not instanceof NanoStateClass")},setCurrentState:function(e){if("undefined"==typeof e||!e)return reportError("ERROR: No state key was passed!"),!1;if(!r.hasOwnProperty(e))return reportError("ERROR: Attempted to set a current state which does not exist: "+e),!1;var t=o;return o=r[e],null!=t&&t.onRemove(o),o.onAdd(t),!0},getCurrentState:function(){return o},getData:function(){return t}}}(),NanoBaseCallbacks=function(){var e=!0,t={},n={status:function(t){var n;return 2==t.config.status?(n="good",$(".linkActive").removeClass("inactive")):1==t.config.status?(n="average",$(".linkActive").addClass("inactive")):(n="bad",$(".linkActive").addClass("inactive")),$(".statusicon").removeClass("good bad average").addClass(n),$(".linkActive").stopTime("linkPending"),$(".linkActive").removeClass("linkPending"),$(".linkActive").off("click").on("click",function(n){n.preventDefault();var a=$(this).data("href");null!=a&&e&&(e=!1,$("body").oneTime(300,"enableClick",function(){e=!0}),2==t.config.status&&$(this).oneTime(300,"linkPending",function(){$(this).addClass("linkPending")}),window.location.href=a)}),t},nanomap:function(e){return $(".mapIcon").off("mouseenter mouseleave").on("mouseenter",function(e){$("#uiMapTooltip").html($(this).children(".tooltip").html()).show().stopTime().oneTime(5e3,"hideTooltip",function(){$(this).fadeOut(500)})}),$(".zoomLink").off("click").on("click",function(e){e.preventDefault();var t=$(this).data("zoomLevel"),n=$("#uiMap"),a=n.width()*t,r=n.height()*t;n.css({zoom:t,left:"50%",top:"50%",marginLeft:"-"+Math.floor(a/2)+"px",marginTop:"-"+Math.floor(r/2)+"px"})}),$("#uiMapImage").attr("src","nanomap_z"+e.config.mapZLevel+".png"),e}};return{addCallbacks:function(){NanoStateManager.addBeforeUpdateCallbacks(t),NanoStateManager.addAfterUpdateCallbacks(n)},removeCallbacks:function(){for(var e in t)t.hasOwnProperty(e)&&NanoStateManager.removeBeforeUpdateCallback(e);for(var e in n)n.hasOwnProperty(e)&&NanoStateManager.removeAfterUpdateCallback(e)}}}(),NanoBaseHelpers=function(){var e={syndicateMode:function(){return $("body").css("background-color","#8f1414"),$("body").css("background-image","url('uiBackground-Syndicate.png')"),$("body").css("background-position","50% 0"),$("body").css("background-repeat","repeat-x"),$("#uiTitleFluff").css("background-image","url('uiTitleFluff-Syndicate.png')"),$("#uiTitleFluff").css("background-position","50% 50%"),$("#uiTitleFluff").css("background-repeat","no-repeat"),""},combine:function(e,t){return e&&t?e.concat(t):e||t},dump:function(e){return JSON.stringify(e)},link:function(e,t,n,a,r,o){var i="",s="noIcon";"undefined"!=typeof t&&t&&(i='
',s="hasIcon"),"undefined"!=typeof r&&r||(r="link");var l="";return"undefined"!=typeof o&&o&&(l='id="'+o+'"'),"undefined"!=typeof a&&a?'":'
"+i+e+"
"},xor:function(e,t){return e^t},precisionRound:function(e,t){if(0==t)return Math.round(number);var n=Math.pow(10,t);return Math.round(e*n)/n},round:function(e){return Math.round(e)},fixed:function(e){return Math.round(10*e)/10},floor:function(e){return Math.floor(e)},ceil:function(e){return Math.ceil(e)},string:function(){if(0==arguments.length)return"";if(1==arguments.length)return arguments[0];if(arguments.length>1){stringArgs=[];for(var e=1;et?t>e?e=t:e>n&&(e=n):e>t?e=t:n>e&&(e=n),"undefined"!=typeof a&&a||(a=""),"undefined"!=typeof r&&r||(r="");var o=Math.round((e-t)/(n-t)*100);return'
'+r+"
"},dangerToClass:function(e){return 0==e?"good":1==e?"average":"bad"},dangerToSpan:function(e){return 0==e?'"Good"':1==e?'"Minor Alert"':'"Major Alert"'},generateHref:function(e){var t=$("body");_urlParameters=t.data("urlParameters");var n="?";for(var a in _urlParameters)_urlParameters.hasOwnProperty(a)&&("?"!==n&&(n+=";"),n+=a+"="+_urlParameters[a]);for(var a in e)e.hasOwnProperty(a)&&("?"!==n&&(n+=";"),n+=a+"="+e[a]);return n},displayDNABlocks:function(e,t,n,a,r){if(!e)return'
Please place a valid subject into the DNA modifier.
';var o=e.split(""),i='
',s=1,l=1;for(var c in o)if(o.hasOwnProperty(c)&&"object"!=typeof o[c]){var u;u="UI"==r.toUpperCase()?{selectUIBlock:s,selectUISubblock:l}:{selectSEBlock:s,selectSESubblock:l};var d="linkActive";s==t&&l==n&&(d="selected"),i+='",c++,c%a==0&&c
"):l++}return i+="
"},cMirror:function(e){CodeMirror.fromTextArea(document.getElementById(e),{lineNumbers:!0,indentUnit:4,indentWithTabs:!0,theme:"lesser-dark"})}};return{addHelpers:function(){NanoTemplate.addHelpers(e)},removeHelpers:function(){for(var t in e)e.hasOwnProperty(t)&&NanoTemplate.removeHelper(t)}}}(),NanoStateDefaultClass.inheritsFrom(NanoStateClass);var NanoStateDefault=new NanoStateDefaultClass;NanoStatePDAClass.inheritsFrom(NanoStateClass);var NanoStatePDA=new NanoStatePDAClass,pda_app_template=null;NanoStatePDAClass.prototype.onUpdate=function(e){NanoStateClass.prototype.onUpdate.call(this,e);try{if(null!=e.data.app){var t=e.data.app.template;null!=t&&t!=pda_app_template?$.when($.ajax({url:t+".tmpl",cache:!1,dataType:"text"})).done(function(n){n+='
';try{NanoTemplate.addTemplate("app",n),NanoTemplate.resetTemplate("app"),$("#uiApp").html(NanoTemplate.parse("app",e)),pda_app_template=t,2==e.config.status&&($("#uiApp .linkActive").addClass("linkPending"),$("#uiApp .linkActive").oneTime(300,"linkPending",function(){$("#uiApp .linkActive").removeClass("linkPending inactive")}))}catch(a){return void reportError("ERROR: An error occurred while loading the UI: "+a.message)}}).fail(function(){reportError("ERROR: Loading template app("+t+") failed!")}):NanoTemplate.templateExists("app")&&$("#uiApp").html(NanoTemplate.parse("app",e))}}catch(n){return void reportError("ERROR: An error occurred while rendering the UI: "+n.message)}},NanoStateClass.prototype.key=null,NanoStateClass.prototype.layoutRendered=!1,NanoStateClass.prototype.contentRendered=!1,NanoStateClass.prototype.mapInitialised=!1,NanoStateClass.prototype.isCurrent=function(){return NanoStateManager.getCurrentState()==this},NanoStateClass.prototype.onAdd=function(e){NanoBaseCallbacks.addCallbacks(),NanoBaseHelpers.addHelpers()},NanoStateClass.prototype.onRemove=function(e){NanoBaseCallbacks.removeCallbacks(),NanoBaseHelpers.removeHelpers()},NanoStateClass.prototype.onBeforeUpdate=function(e){return e=NanoStateManager.executeBeforeUpdateCallbacks(e)},NanoStateClass.prototype.onUpdate=function(e){try{(!this.layoutRendered||e.config.hasOwnProperty("autoUpdateLayout")&&e.config.autoUpdateLayout)&&($("#uiLayout").html(NanoTemplate.parse("layout",e)),this.layoutRendered=!0),(!this.contentRendered||e.config.hasOwnProperty("autoUpdateContent")&&e.config.autoUpdateContent)&&($("#uiContent").html(NanoTemplate.parse("main",e)),this.contentRendered=!0),NanoTemplate.templateExists("mapContent")&&(this.mapInitialised||($("#uiMap").draggable(),$("#uiMapTooltip").off("click").on("click",function(e){e.preventDefault(),$(this).fadeOut(400)}),this.mapInitialised=!0),$("#uiMapContent").html(NanoTemplate.parse("mapContent",e)),e.config.hasOwnProperty("showMap")&&e.config.showMap?($("#uiContent").addClass("hidden"),$("#uiMapWrapper").removeClass("hidden")):($("#uiMapWrapper").addClass("hidden"),$("#uiContent").removeClass("hidden"))),NanoTemplate.templateExists("mapHeader")&&$("#uiMapHeader").html(NanoTemplate.parse("mapHeader",e)),NanoTemplate.templateExists("mapFooter")&&$("#uiMapFooter").html(NanoTemplate.parse("mapFooter",e))}catch(t){return void reportError("ERROR: An error occurred while rendering the UI: "+t.message)}},NanoStateClass.prototype.onAfterUpdate=function(e){NanoStateManager.executeAfterUpdateCallbacks(e)},NanoStateClass.prototype.alertText=function(e){alert(e)};var NanoTemplate=function(){var e={},t={},n={},a={},r=function(){e=$("body").data("templateData"),null==e&&reportError("Error: Template data did not load correctly."),o()},o=function(){var t=Object.size(e);if(!t)return void $(document).trigger("templatesLoaded");for(var n in e)if(e.hasOwnProperty(n))return void $.when($.ajax({url:e[n],cache:!1,dataType:"text"})).done(function(t){t+='
';try{NanoTemplate.addTemplate(n,t)}catch(a){return void reportError("ERROR: An error occurred while loading the UI: "+a.message)}delete e[n],o()}).fail(function(){reportError("ERROR: Loading template "+n+"("+e[n]+") failed!")})},i=function(){for(var e in t)try{n[e]=doT.template(t[e],null,t)}catch(a){reportError(a.message)}};return{init:function(){r()},addTemplate:function(e,n){t[e]=n},templateExists:function(e){return t.hasOwnProperty(e)},resetTemplate:function(e){n[e]=null},parse:function(e,r){if(!n.hasOwnProperty(e)||!n[e]){if(!t.hasOwnProperty(e))return reportError('ERROR: Template "'+e+'" does not exist in _compiledTemplates!'),"

Template error (does not exist)

";i()}return"function"!=typeof n[e]?(reportError(n[e]),reportError('ERROR: Template "'+e+'" failed to compile!'),"

Template error (failed to compile)

"):n[e].call(this,r.data,r.config,a)},addHelper:function(e,t){return jQuery.isFunction(t)?void(a[e]=t):void reportError("NanoTemplate.addHelper failed to add "+e+" as it is not a function.")},addHelpers:function(e){for(var t in e)e.hasOwnProperty(t)&&NanoTemplate.addHelper(t,e[t])},removeHelper:function(e){helpers.hasOwnProperty(e)&&delete a[e]}}}(),NanoWindow=function(){var e,t,n,a,r,o,i=function(e,t){NanoUtility.winset("pos",e+","+t)},s=function(e,t){NanoUtility.winset("size",e+","+t)},l=function(){NanoStateManager.getData().config.user.fancy&&(c(),u(),d(),f())},c=function(){NanoUtility.winset("titlebar",0),NanoUtility.winset("can-resize",0),$(".fancy").show(),$("#uiTitleFluff").css("right","65px")},u=function(){var e=function(){return NanoUtility.close()},t=function(){return NanoUtility.winset("is-minimized","true")};$(".close").on("click",function(t){e()}),$(".minimize").on("click",function(e){t()})},d=function(){$("#uiTitleWrapper").on("mousemove",function(e){p()}),$("#uiTitleWrapper").on("mousedown",function(t){e=!0}),$("#uiTitleWrapper").on("mouseup",function(a){e=!1,t=null,n=null})},p=function(a){var r,o;null==a&&(a=window.event),e&&(null==t&&(t=a.screenX),null==n&&(n=a.screenY),r=a.screenX-t+window.screenLeft,o=a.screenY-n+window.screenTop,i(r,o),t=a.screenX,n=a.screenY)},f=function(){$("#resize").on("mousemove",function(e){m()}),$("#resize").on("mousedown",function(e){a=!0}),$("#resize").on("mouseup",function(e){a=!1})},m=function(){var e,t;null==event&&(event=window.event),a&&(null==r&&(r=event.screenX),null==o&&(o=event.screenY),e=Math.max(150,event.screenX-r+window.innerWidth),t=Math.max(150,event.screenY-o+window.innerHeight),s(e,t),r=event.screenX,o=event.screenY)};return{init:function(){$(document).on("templatesLoaded",function(){l()})}}}(); \ No newline at end of file diff --git a/nano/assets/nanoui.css b/nano/assets/nanoui.css index e99b2f94fd5..b4006f704b1 100644 --- a/nano/assets/nanoui.css +++ b/nano/assets/nanoui.css @@ -1,2 +1,2 @@ @font-face{font-family:FontAwesome;src:url(fontawesome-webfont.eot?v=4.5.0);src:url(fontawesome-webfont.eot?#iefix&v=4.5.0) format('embedded-opentype'),url(fontawesome-webfont.woff2?v=4.5.0) format('woff2'),url(fontawesome-webfont.woff?v=4.5.0) format('woff'),url(fontawesome-webfont.ttf?v=4.5.0) format('truetype'),url(fontawesome-webfont.svg?v=4.5.0#fontawesomeregular) format('svg');font-weight:400;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:.08em solid #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:a 2s infinite linear;animation:a 2s infinite linear}.fa-pulse{-webkit-animation:a 1s infinite steps(8);animation:a 1s infinite steps(8)}@-webkit-keyframes a{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes a{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0,mirror=1);-webkit-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2,mirror=1);-webkit-transform:scaleY(-1);transform:scaleY(-1)}:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-close:before,.fa-remove:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-cog:before,.fa-gear:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-repeat:before,.fa-rotate-right:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-image:before,.fa-photo:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-exclamation-triangle:before,.fa-warning:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-cogs:before,.fa-gears:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-floppy-o:before,.fa-save:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-bars:before,.fa-navicon:before,.fa-reorder:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-sort:before,.fa-unsorted:before{content:"\f0dc"}.fa-sort-desc:before,.fa-sort-down:before{content:"\f0dd"}.fa-sort-asc:before,.fa-sort-up:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-gavel:before,.fa-legal:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-bolt:before,.fa-flash:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-clipboard:before,.fa-paste:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-chain-broken:before,.fa-unlink:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-caret-square-o-down:before,.fa-toggle-down:before{content:"\f150"}.fa-caret-square-o-up:before,.fa-toggle-up:before{content:"\f151"}.fa-caret-square-o-right:before,.fa-toggle-right:before{content:"\f152"}.fa-eur:before,.fa-euro:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-inr:before,.fa-rupee:before{content:"\f156"}.fa-cny:before,.fa-jpy:before,.fa-rmb:before,.fa-yen:before{content:"\f157"}.fa-rouble:before,.fa-rub:before,.fa-ruble:before{content:"\f158"}.fa-krw:before,.fa-won:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-caret-square-o-left:before,.fa-toggle-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-try:before,.fa-turkish-lira:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-bank:before,.fa-institution:before,.fa-university:before{content:"\f19c"}.fa-graduation-cap:before,.fa-mortar-board:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-image-o:before,.fa-file-photo-o:before,.fa-file-picture-o:before{content:"\f1c5"}.fa-file-archive-o:before,.fa-file-zip-o:before{content:"\f1c6"}.fa-file-audio-o:before,.fa-file-sound-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-ring:before,.fa-life-saver:before,.fa-support:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-rebel:before{content:"\f1d0"}.fa-empire:before,.fa-ge:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-hacker-news:before,.fa-y-combinator-square:before,.fa-yc-square:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-paper-plane:before,.fa-send:before{content:"\f1d8"}.fa-paper-plane-o:before,.fa-send-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-futbol-o:before,.fa-soccer-ball-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-ils:before,.fa-shekel:before,.fa-sheqel:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-bed:before,.fa-hotel:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-y-combinator:before,.fa-yc:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-paper-o:before,.fa-hand-stop-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-television:before,.fa-tv:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"} -.displayBar{position:relative;width:236px;height:16px;border:1px solid #666;float:left;margin:0 5px 0 0;overflow:hidden;background:#000}.displayBarText{position:absolute;top:-2px;left:5px;width:100%;height:100%;color:#fff;font-weight:400}.displayBarFill{width:0;height:100%;background:#40628a;overflow:hidden;float:left}.displayBarFill.alignRight{float:right}.displayBarFill.good{color:#fff;background:#4f7529}.displayBarFill.notgood{color:#fff;background:#ffb400}.displayBarFill.average{color:#fff;background:#cd6500}.displayBarFill.bad{color:#fff;background:#e00}.displayBarFill.highlight{color:#fff;background:#8ba5c4}.disabled,.link,.linkOff,.linkOn,.redButton,.selected,.yellowButton{float:left;min-width:15px;height:16px;text-align:center;color:#fff;text-decoration:none;background:#40628a;border:1px solid #161616;padding:0 4px 4px;margin:0 2px 2px 0;cursor:default;white-space:nowrap}.hasIcon{padding:0 4px 4px 0}.linkActive:hover,.zoomLink:hover,a:hover{background:#507aac}.linkPending,.linkPending:hover{color:#fff;background:#507aac}a.white,a.white:active,a.white:link,a.white:visited{color:#40628a;text-decoration:none;background:#fff;border:1px solid #161616;padding:1px 4px;margin:0 2px 0 0;cursor:default}a.white:hover{color:#fff;background:#40628a}.linkOn,.selected,a.linkOn:active,a.linkOn:hover,a.linkOn:link,a.linkOn:visited,a.selected:active,a.selected:hover,a.selected:link,a.selected:visited{color:#fff;background:#2f943c}.disabled,.linkOff,a.disabled:active,a.disabled:hover,a.disabled:link,a.disabled:visited,a.linkOff:active,a.linkOff:hover,a.linkOff:link,a.linkOff:visited{color:#fff;background:#999;border-color:#666}.disabled.icon,.linkOff.icon,.linkOn.icon,.selected.icon,a.icon{position:relative;padding:1px 4px 2px 20px}.disabled.icon img,.linkOff.icon img,.linkOn.icon img,.selected.icon img,a.icon img{position:absolute;top:0;left:0;width:18px;height:18px}.linkDanger,a.linkDanger:active,a.linkDanger:link,a.linkDanger:visited{color:#fff;background-color:red;border-color:#a00}.linkDanger:hover{background-color:#f66}.inactive,a.inactive:active,a.inactive:hover,a.inactive:link,a.inactive:visited{color:#fff;background:#999;border-color:#666}.white{color:#fff}.good,.white{font-weight:700}.good{color:#4f7529}.average{color:#cd6500}.average,.bad{font-weight:700}.bad{color:#e00}.idle{color:#272727;font-weight:700}.redButton{background:#ea0000}.yellowButton{background:#cacc00}.highlight{color:#8ba5c4}.dark{color:#272727}.burn{color:orange}.brute{color:red}.toxin{color:green}.toxin_light{color:#3adf00}.oxyloss{color:blue}.oxyloss_light{color:#6698ff}.Red{color:red}.Blue{color:#00f}.Green{color:#0f0}.Marigold{color:#fda505}.Fuschia{color:#ff0080}.Black{color:#000}.Pearl{color:#c6cacb}.cold1{color:#94b8ff}.cold2{color:#69f}.cold3{color:#293d66}.hot1{color:#f96}.hot2{color:#993d00}.hot3{color:#f60}.itemGroup{border:1px solid #e9c183;background:#2c2c2c;padding:4px;clear:both}.item{width:100%;margin:4px 0 0;clear:both;overflow:auto}.itemContent,.itemContentNarrow{float:left}.itemContentNarrow{width:30%}.itemContent{width:69%}.itemLabel,.itemLabelNarrow,.itemLabelWide,.itemLabelWider,.itemLabelWidest{float:left;color:#e9c183}.itemLabelNarrow{width:20%}.itemLabel{width:30%}.itemLabelWide{width:45%}.itemLabelWider{width:69%}.itemLabelWidest{width:100%}.itemContentWide{float:left;width:79%}.itemContentSmall{float:left;width:33%}.itemContentMedium{float:left;width:55%}.block{padding:8px;margin:10px 4px 4px;border:1px solid #40628a;background-color:#202020}.block h3{padding:0}.clearBoth{clear:both}.clearLeft{clear:left}.clearRight{clear:right}.line{width:100%;clear:both}.fixedLeft{width:110px;float:left}.fixedLeftWide{width:165px;float:left}.fixedLeftWider{width:220px;float:left}.fixedLeftWidest{width:250px;float:left}.floatRight{float:right}.floatLeft{float:left}.hidden{display:none}.statusDisplay{overflow:hidden}.statusDisplay,.statusDisplayRecords{background:#000;-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorStr=#80000000,endColorStr=#80000000)";filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#80000000,endColorStr=#80000000);background:rgba(0,0,0,.5);color:#fff;border:1px solid #40628a;padding:4px;margin:3px 0}.statusDisplayRecords{overflow-x:hidden;overflow-y:auto}.statusLabel{width:138px;float:left;overflow:hidden;color:#98b0c3}.statusValue{float:left}.fancy{display:none}.minimize{color:#e9c183;position:absolute;top:6px;right:46px}.minimize:hover{color:#b8c9d6}.close{color:#e9c183;position:absolute;top:4px;right:12px}.close:hover{color:#b8c9d6}div.resize{position:fixed;bottom:0;right:0;width:0;height:0;border-style:solid;border-width:0 0 30px 30px;border-color:transparent transparent #363636;-webkit-transform:rotate(1turn);transform:rotate(1turn)}.uiLinkPendingIcon{display:none;float:left;width:16px;height:16px;margin:2px 2px 0;background-image:url(uiLinkPendingIcon.gif)}.linkPending .fa{display:none}.linkPending .uiLinkPendingIcon{display:block}.mapIcon16{position:absolute;width:16px;height:16px;background-image:url(uiIcons16Green.png);background-position:-144px -96px;background-repeat:no-repeat;zoom:.125;margin-left:-1px}.mapIcon16.bad,.mapIcon16.dead{background-image:url(uiIcons16Red.png)}.mapIcon16.average{background-image:url(uiIcons16Orange.png)}.mapIcon16.good{background-image:url(uiIcons16Green.png)}.mapIcon16.icon-airalarm{background-position:0 -144px}.mapIcon16.rank-captain{background-position:-224px -112px}.mapIcon16.rank-headofpersonnel{background-position:-112px -96px}.mapIcon16.rank-headofsecurity{background-position:-112px -128px}.mapIcon16.rank-chiefengineer{background-position:-176px -112px}.mapIcon16.rank-researchdirector{background-position:-128px -128px}.mapIcon16.rank-chiefmedicalofficer{background-position:-32px -128px}.mapIcon16.rank-atmospherictechnician,.mapIcon16.rank-stationengineer{background-position:-176px -112px}.mapIcon16.rank-chemist,.mapIcon16.rank-geneticist,.mapIcon16.rank-medicaldoctor,.mapIcon16.rank-psychiatrist{background-position:-32px -128px}.mapIcon16.rank-geneticist,.mapIcon16.rank-roboticist,.mapIcon16.rank-scientist,.mapIcon16.rank-xenobiologist{background-position:-128px -128px}.mapIcon16.rank-detective,.mapIcon16.rank-securityofficer,.mapIcon16.rank-warden{background-position:-112px -128px}ul{padding:4px 0 0 10px;margin:0;list-style-type:none}li{padding:0 0 2px}table.fixed{table-layout:fixed}table.fixed td{overflow:hidden}table.pmon{border:2px solid #4169e1}table.pmon td,table.pmon th{border-bottom:1px dotted #000;padding:0 5px}th.command{background:#33f}th.command,th.sec{font-weight:700;color:#fff}th.sec{background:#8e0000}th.med{background:#060}th.eng,th.med{font-weight:700;color:#fff}th.eng{background:#b27300}th.sci{background:#a65ba6}th.sci,th.ser{font-weight:700;color:#fff}th.ser{background:#7100aa}th.sup{background:#666621}th.civ,th.sup{font-weight:700;color:#fff}th.civ{background:#a32800}th.misc{background:#666;font-weight:700;color:#fff}span.qm-job{color:#b77a41;font-weight:700}.striped:not(table)>:nth-child(even),.striped tr:nth-child(even){background-color:#404040}#uiNoScript{position:fixed;top:50%;left:50%;margin:-60px 0 0 -150px;width:280px;height:120px;background:#fff;border:2px solid red;color:#000;font-size:10px;font-weight:700;z-index:1;padding:0 10px;text-align:center}.notice{background:url(uiNoticeBackground.jpg) 50% 50%;color:#000}.notice,.noticePlaceholder{position:relative;font-size:12px;font-style:italic;font-weight:700;padding:3px 4px;margin:4px 0}.notice.icon{padding:2px 4px 0 20px}.notice img{position:absolute;top:0;left:0;width:16px;height:16px}div.notice{clear:both}.wholeScreen{position:absolute;color:#517087;font-size:16px;font-weight:700;text-align:center}.pdalink{float:left;white-space:nowrap}.pdanote{color:#cd6500;font-weight:700}.dnaBlock{float:left;width:90px;padding:0 0 5px}.dnaBlockNumber{color:#fff;background:#363636;min-width:20px}.dnaBlockNumber,.dnaSubBlock{font-family:Fixed,monospace;float:left;height:20px;padding:0;text-align:center}.dnaSubBlock{min-width:16px}.mask{position:fixed;left:0;top:0;width:100%;height:100%;background:url(uiMaskBackground.png)}.maskContent{width:100%;height:200px;margin:200px 0;text-align:center}body{background:#272727;color:#fff;font-family:Verdana,Geneva,sans-serif;font-size:12px;line-height:170%;margin:0;padding:0}hr{background-color:#40628a;height:1px;border:none}a img,img{border-style:none}h1,h2,h3,h4,h5,h6{margin:0;padding:12px 0 6px;color:#fff;clear:both}h1{font-size:18px}h2{font-size:16px}h3{font-size:14px}h4{font-size:12px}body{background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' version='1' viewBox='0 0 425 200' opacity='.25'%3E%3Cpath d='M178.004.04H106.8a6.76 6.026 0 0 0-6.76 6.024v187.872a6.76 6.026 0 0 0 6.76 6.025h53.107a6.76 6.026 0 0 0 6.762-6.024V92.392l72.215 104.7a6.76 6.026 0 0 0 5.76 2.87H318.2a6.76 6.026 0 0 0 6.76-6.026V6.064A6.76 6.026 0 0 0 318.2.04h-54.717a6.76 6.026 0 0 0-6.76 6.024v102.62L183.762 2.91a6.76 6.026 0 0 0-5.76-2.87zM4.845 22.11A13.412 12.502 0 0 1 13.478.04h66.118a5.365 5 0 0 1 5.365 5v79.88zM420.155 177.89a13.412 12.502 0 0 1-8.633 22.07h-66.118a5.365 5 0 0 1-5.365-5v-79.88z'/%3E%3C/svg%3E") no-repeat fixed center/70% 70%,linear-gradient(180deg,#2a2a2a 0,#202020) no-repeat fixed center/100% 100%;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff2a2a2a',endColorstr='#ff000000',GradientType=0)}#uiWrapper{width:100%;height:100%;-ms-user-select:none;-webkit-user-select:none;-moz-user-select:none;user-select:none}#uiTitleWrapper{position:relative;height:30px}#uiTitleText{position:absolute;top:6px;left:44px;width:66%;overflow:hidden;color:#e9c183;font-size:16px}#uiTitle.icon{padding:6px 8px 6px 42px;background-position:2px 50%;background-repeat:no-repeat}#uiTitleFluff{position:absolute;top:4px;right:12px;width:42px;height:24px;background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' version='1' viewBox='0 0 425 200' opacity='.25'%3E%3Cpath d='M178.004.04H106.8a6.76 6.026 0 0 0-6.76 6.024v187.872a6.76 6.026 0 0 0 6.76 6.025h53.107a6.76 6.026 0 0 0 6.762-6.024V92.392l72.215 104.7a6.76 6.026 0 0 0 5.76 2.87H318.2a6.76 6.026 0 0 0 6.76-6.026V6.064A6.76 6.026 0 0 0 318.2.04h-54.717a6.76 6.026 0 0 0-6.76 6.024v102.62L183.762 2.91a6.76 6.026 0 0 0-5.76-2.87zM4.845 22.11A13.412 12.502 0 0 1 13.478.04h66.118a5.365 5 0 0 1 5.365 5v79.88zM420.155 177.89a13.412 12.502 0 0 1-8.633 22.07h-66.118a5.365 5 0 0 1-5.365-5v-79.88z'/%3E%3C/svg%3E") 50% 50% no-repeat}.statusicon{position:absolute;top:4px;left:12px}#uiMapWrapper{clear:both;padding:8px}#uiMapHeader{position:relative;clear:both}#uiMapContainer{position:relative;width:100%;height:600px;overflow:hidden;border:1px solid #40628a;background:url(nanomapBackground.png)}#uiMap{top:50%;left:50%;margin:-512px 0 0 -512px;overflow:hidden;zoom:4}#uiMap,#uiMapImage{position:absolute;width:256px;height:256px}#uiMapImage{bottom:1px;left:1px}#uiMapContent{position:absolute;bottom:-13.5px;left:0;width:256px;height:256px}#uiMapFooter{position:relative;clear:both}#uiContent{clear:both;padding:8px}#uiMapTooltip{position:absolute;right:10px;top:10px;border:1px solid #40628a;background-color:#272727;padding:8px;display:none;z-index:1}#uiLoadingNotice{position:relative;background:url(uiNoticeBackground.jpg) 50% 50%;color:#000;font-size:14px;font-style:italic;font-weight:700;padding:3px 4px;margin:4px 0} \ No newline at end of file +.displayBar{position:relative;width:236px;height:16px;border:1px solid #666;float:left;margin:0 5px 0 0;overflow:hidden;background:#000}.displayBarText{position:absolute;top:-2px;left:5px;width:100%;height:100%;color:#fff;font-weight:400}.displayBarFill{width:0;height:100%;background:#40628a;overflow:hidden;float:left}.displayBarFill.alignRight{float:right}.displayBarFill.good{color:#fff;background:#4f7529}.displayBarFill.notgood{color:#fff;background:#ffb400}.displayBarFill.average{color:#fff;background:#cd6500}.displayBarFill.bad{color:#fff;background:#e00}.displayBarFill.highlight{color:#fff;background:#8ba5c4}.disabled,.link,.linkOff,.linkOn,.redButton,.selected,.yellowButton{float:left;min-width:15px;height:16px;text-align:center;color:#fff;text-decoration:none;background:#40628a;border:1px solid #161616;padding:0 4px 4px;margin:0 2px 2px 0;cursor:default;white-space:nowrap}.hasIcon{padding:0 4px 4px 0}.linkActive:hover,.zoomLink:hover,a:hover{background:#507aac}.linkPending,.linkPending:hover{color:#fff;background:#507aac}a.white,a.white:active,a.white:link,a.white:visited{color:#40628a;text-decoration:none;background:#fff;border:1px solid #161616;padding:1px 4px;margin:0 2px 0 0;cursor:default}a.white:hover{color:#fff;background:#40628a}.linkOn,.selected,a.linkOn:active,a.linkOn:hover,a.linkOn:link,a.linkOn:visited,a.selected:active,a.selected:hover,a.selected:link,a.selected:visited{color:#fff;background:#2f943c}.disabled,.linkOff,a.disabled:active,a.disabled:hover,a.disabled:link,a.disabled:visited,a.linkOff:active,a.linkOff:hover,a.linkOff:link,a.linkOff:visited{color:#fff;background:#999;border-color:#666}.disabled.icon,.linkOff.icon,.linkOn.icon,.selected.icon,a.icon{position:relative;padding:1px 4px 2px 20px}.disabled.icon img,.linkOff.icon img,.linkOn.icon img,.selected.icon img,a.icon img{position:absolute;top:0;left:0;width:18px;height:18px}.linkDanger,a.linkDanger:active,a.linkDanger:link,a.linkDanger:visited{color:#fff;background-color:red;border-color:#a00}.linkDanger:hover{background-color:#f66}.inactive,a.inactive:active,a.inactive:hover,a.inactive:link,a.inactive:visited{color:#fff;background:#999;border-color:#666}.white{color:#fff}.good,.white{font-weight:700}.good{color:#4f7529}.average{color:#cd6500}.average,.bad{font-weight:700}.bad{color:#e00}.idle{color:#272727;font-weight:700}.redButton{background:#ea0000}.yellowButton{background:#cacc00}.highlight{color:#8ba5c4}.dark{color:#272727}.burn{color:orange}.brute{color:red}.toxin{color:green}.toxin_light{color:#3adf00}.oxyloss{color:blue}.oxyloss_light{color:#6698ff}.Red{color:red}.Blue{color:#00f}.Green{color:#0f0}.Marigold{color:#fda505}.Fuschia{color:#ff0080}.Black{color:#000}.Pearl{color:#c6cacb}.cold1{color:#94b8ff}.cold2{color:#69f}.cold3{color:#293d66}.hot1{color:#f96}.hot2{color:#993d00}.hot3{color:#f60}.itemGroup{border:1px solid #e9c183;background:#2c2c2c;padding:4px;clear:both}.item{width:100%;margin:4px 0 0;clear:both;overflow:auto}.itemContent,.itemContentNarrow{float:left}.itemContentNarrow{width:30%}.itemContent{width:69%}.itemLabel,.itemLabelNarrow,.itemLabelWide,.itemLabelWider,.itemLabelWidest{float:left;color:#e9c183}.itemLabelNarrow{width:20%}.itemLabel{width:30%}.itemLabelWide{width:45%}.itemLabelWider{width:69%}.itemLabelWidest{width:100%}.itemContentWide{float:left;width:79%}.itemContentSmall{float:left;width:33%}.itemContentMedium{float:left;width:55%}.block{padding:8px;margin:10px 4px 4px;border:1px solid #40628a;background-color:#202020}.block h3{padding:0}.clearBoth{clear:both}.clearLeft{clear:left}.clearRight{clear:right}.line{width:100%;clear:both}.fixedLeft{width:110px;float:left}.fixedLeftWide{width:165px;float:left}.fixedLeftWider{width:220px;float:left}.fixedLeftWidest{width:250px;float:left}.floatRight{float:right}.floatLeft{float:left}.hidden{display:none}.statusDisplay{overflow:hidden}.statusDisplay,.statusDisplayRecords{background:#000;-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorStr=#80000000,endColorStr=#80000000)";filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#80000000,endColorStr=#80000000);background:rgba(0,0,0,.5);color:#fff;border:1px solid #40628a;padding:4px;margin:3px 0}.statusDisplayRecords{overflow-x:hidden;overflow-y:auto}.statusLabel{width:138px;float:left;overflow:hidden;color:#98b0c3}.statusValue{float:left}.fancy{display:none}.minimize{color:#e9c183;position:absolute;top:6px;right:46px}.minimize:hover{color:#b8c9d6}.close{color:#e9c183;position:absolute;top:4px;right:12px}.close:hover{color:#b8c9d6}div.resize{position:fixed;bottom:0;right:0;width:0;height:0;border-style:solid;border-width:0 0 30px 30px;border-color:transparent transparent #363636;-webkit-transform:rotate(1turn);transform:rotate(1turn)}.uiLinkPendingIcon{display:none;float:left;width:16px;height:16px;margin:2px 2px 0;background-image:url(uiLinkPendingIcon.gif)}.linkPending .fa{display:none}.linkPending .uiLinkPendingIcon{display:block}.mapIcon16{position:absolute;width:16px;height:16px;background-image:url(uiIcons16Green.png);background-position:-144px -96px;background-repeat:no-repeat;zoom:.125;margin-left:-1px}.mapIcon16.bad,.mapIcon16.dead{background-image:url(uiIcons16Red.png)}.mapIcon16.average{background-image:url(uiIcons16Orange.png)}.mapIcon16.good{background-image:url(uiIcons16Green.png)}.mapIcon16.icon-airalarm{background-position:0 -144px}.mapIcon16.rank-captain{background-position:-224px -112px}.mapIcon16.rank-headofpersonnel{background-position:-112px -96px}.mapIcon16.rank-headofsecurity{background-position:-112px -128px}.mapIcon16.rank-chiefengineer{background-position:-176px -112px}.mapIcon16.rank-researchdirector{background-position:-128px -128px}.mapIcon16.rank-chiefmedicalofficer{background-position:-32px -128px}.mapIcon16.rank-atmospherictechnician,.mapIcon16.rank-stationengineer{background-position:-176px -112px}.mapIcon16.rank-chemist,.mapIcon16.rank-geneticist,.mapIcon16.rank-medicaldoctor,.mapIcon16.rank-psychiatrist{background-position:-32px -128px}.mapIcon16.rank-geneticist,.mapIcon16.rank-roboticist,.mapIcon16.rank-scientist,.mapIcon16.rank-xenobiologist{background-position:-128px -128px}.mapIcon16.rank-detective,.mapIcon16.rank-securityofficer,.mapIcon16.rank-warden{background-position:-112px -128px}ul{padding:4px 0 0 10px;margin:0;list-style-type:none}li{padding:0 0 2px}table.fixed{table-layout:fixed}table.fixed td{overflow:hidden}table.pmon{border:2px solid #4169e1}table.pmon td,table.pmon th{border-bottom:1px dotted #000;padding:0 5px}th.command{background:#33f}th.command,th.sec{font-weight:700;color:#fff}th.sec{background:#8e0000}th.med{background:#060}th.eng,th.med{font-weight:700;color:#fff}th.eng{background:#b27300}th.sci{background:#a65ba6}th.sci,th.ser{font-weight:700;color:#fff}th.ser{background:#7100aa}th.sup{background:#666621}th.civ,th.sup{font-weight:700;color:#fff}th.civ{background:#a32800}th.misc{background:#666;font-weight:700;color:#fff}span.qm-job{color:#b77a41;font-weight:700}.striped:not(table)>:nth-child(even),.striped tr:nth-child(even){background-color:#404040}#uiNoScript{position:fixed;top:50%;left:50%;margin:-60px 0 0 -150px;width:280px;height:120px;background:#fff;border:2px solid red;color:#000;font-size:10px;font-weight:700;z-index:1;padding:0 10px;text-align:center}.notice{background:url(uiNoticeBackground.jpg) 50% 50%;color:#000}.notice,.noticePlaceholder{position:relative;font-size:12px;font-style:italic;font-weight:700;padding:3px 4px;margin:4px 0}.notice.icon{padding:2px 4px 0 20px}.notice img{position:absolute;top:0;left:0;width:16px;height:16px}div.notice{clear:both}.wholeScreen{position:absolute;color:#517087;font-size:16px;font-weight:700;text-align:center}.pdalink{float:left;white-space:nowrap;cursor:default!important}.pdalink.disabled{background:none;border:none;color:#999;text-align:left}.pdanote{color:#cd6500;font-weight:700}.item.mainmenu{padding-bottom:.5em}div.clock{color:#fff;font-weight:700;float:right;padding-right:2em}#pdaFooter{position:fixed;left:0;bottom:0;width:100%;background:#272727}.pdaFooterButton{width:33%;padding:.5em 0;font-size:200%;border:none;background:none;color:#fff}.pdaFooterButton:hover{background:#507aac}.pdaFooterButton.disabled{background:none!important;color:#555!important}.pdaFooterButton .uiLinkPendingIcon{position:absolute;width:33%;background-repeat:no-repeat;background-position:center}.dnaBlock{float:left;width:90px;padding:0 0 5px}.dnaBlockNumber{color:#fff;background:#363636;min-width:20px}.dnaBlockNumber,.dnaSubBlock{font-family:Fixed,monospace;float:left;height:20px;padding:0;text-align:center}.dnaSubBlock{min-width:16px}.mask{position:fixed;left:0;top:0;width:100%;height:100%;background:url(uiMaskBackground.png)}.maskContent{width:100%;height:200px;margin:200px 0;text-align:center}body{background:#272727;color:#fff;font-family:Verdana,Geneva,sans-serif;font-size:12px;line-height:170%;margin:0;padding:0}hr{background-color:#40628a;height:1px;border:none}a img,img{border-style:none}h1,h2,h3,h4,h5,h6{margin:0;padding:12px 0 6px;color:#fff;clear:both}h1{font-size:18px}h2{font-size:16px}h3{font-size:14px}h4{font-size:12px}body{background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' version='1' viewBox='0 0 425 200' opacity='.25'%3E%3Cpath d='M178.004.04H106.8a6.76 6.026 0 0 0-6.76 6.024v187.872a6.76 6.026 0 0 0 6.76 6.025h53.107a6.76 6.026 0 0 0 6.762-6.024V92.392l72.215 104.7a6.76 6.026 0 0 0 5.76 2.87H318.2a6.76 6.026 0 0 0 6.76-6.026V6.064A6.76 6.026 0 0 0 318.2.04h-54.717a6.76 6.026 0 0 0-6.76 6.024v102.62L183.762 2.91a6.76 6.026 0 0 0-5.76-2.87zM4.845 22.11A13.412 12.502 0 0 1 13.478.04h66.118a5.365 5 0 0 1 5.365 5v79.88zM420.155 177.89a13.412 12.502 0 0 1-8.633 22.07h-66.118a5.365 5 0 0 1-5.365-5v-79.88z'/%3E%3C/svg%3E") no-repeat fixed center/70% 70%,linear-gradient(180deg,#2a2a2a 0,#202020) no-repeat fixed center/100% 100%;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff2a2a2a',endColorstr='#ff000000',GradientType=0)}#uiWrapper{width:100%;height:100%;-ms-user-select:none;-webkit-user-select:none;-moz-user-select:none;user-select:none}#uiTitleWrapper{position:relative;height:30px}#uiTitleText{position:absolute;top:6px;left:44px;width:66%;overflow:hidden;color:#e9c183;font-size:16px}#uiTitle.icon{padding:6px 8px 6px 42px;background-position:2px 50%;background-repeat:no-repeat}#uiTitleFluff{position:absolute;top:4px;right:12px;width:42px;height:24px;background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' version='1' viewBox='0 0 425 200' opacity='.25'%3E%3Cpath d='M178.004.04H106.8a6.76 6.026 0 0 0-6.76 6.024v187.872a6.76 6.026 0 0 0 6.76 6.025h53.107a6.76 6.026 0 0 0 6.762-6.024V92.392l72.215 104.7a6.76 6.026 0 0 0 5.76 2.87H318.2a6.76 6.026 0 0 0 6.76-6.026V6.064A6.76 6.026 0 0 0 318.2.04h-54.717a6.76 6.026 0 0 0-6.76 6.024v102.62L183.762 2.91a6.76 6.026 0 0 0-5.76-2.87zM4.845 22.11A13.412 12.502 0 0 1 13.478.04h66.118a5.365 5 0 0 1 5.365 5v79.88zM420.155 177.89a13.412 12.502 0 0 1-8.633 22.07h-66.118a5.365 5 0 0 1-5.365-5v-79.88z'/%3E%3C/svg%3E") 50% 50% no-repeat}.statusicon{position:absolute;top:4px;left:12px}#uiMapWrapper{clear:both;padding:8px}#uiMapHeader{position:relative;clear:both}#uiMapContainer{position:relative;width:100%;height:600px;overflow:hidden;border:1px solid #40628a;background:url(nanomapBackground.png)}#uiMap{top:50%;left:50%;margin:-512px 0 0 -512px;overflow:hidden;zoom:4}#uiMap,#uiMapImage{position:absolute;width:256px;height:256px}#uiMapImage{bottom:1px;left:1px}#uiMapContent{position:absolute;bottom:-13.5px;left:0;width:256px;height:256px}#uiMapFooter{position:relative;clear:both}#uiContent{clear:both;padding:8px}#uiMapTooltip{position:absolute;right:10px;top:10px;border:1px solid #40628a;background-color:#272727;padding:8px;display:none;z-index:1}#uiLoadingNotice{position:relative;background:url(uiNoticeBackground.jpg) 50% 50%;color:#000;font-size:14px;font-style:italic;font-weight:700;padding:3px 4px;margin:4px 0} \ No newline at end of file diff --git a/nano/scripts/nano/nano_state_pda.js b/nano/scripts/nano/nano_state_pda.js new file mode 100644 index 00000000000..6277d5669e0 --- /dev/null +++ b/nano/scripts/nano/nano_state_pda.js @@ -0,0 +1,57 @@ +NanoStatePDAClass.inheritsFrom(NanoStateClass); +var NanoStatePDA = new NanoStatePDAClass(); +var pda_app_template = null; + +function NanoStatePDAClass() { + this.key = 'pda'; + this.key = this.key.toLowerCase(); + + NanoStateManager.addState(this); +} + +NanoStatePDAClass.prototype.onUpdate = function(data) { + NanoStateClass.prototype.onUpdate.call(this, data); + + try { + if(data['data']['app'] != null) { + var template = data['data']['app']['template']; + if(template != null && template != pda_app_template) { + $.when($.ajax({ + url: template + '.tmpl', + cache: false, + dataType: 'text' + })) + .done(function(templateMarkup) { + templateMarkup += '
'; + + try { + NanoTemplate.addTemplate('app', templateMarkup); + NanoTemplate.resetTemplate('app'); + $("#uiApp").html(NanoTemplate.parse('app', data)); + pda_app_template = template; + + if(data['config']['status'] == 2) { + $('#uiApp .linkActive').addClass('linkPending'); + $('#uiApp .linkActive').oneTime(300, 'linkPending', function () { + $('#uiApp .linkActive').removeClass('linkPending inactive'); + }); + } + } catch(error) { + reportError('ERROR: An error occurred while loading the UI: ' + error.message); + return; + } + }) + .fail( function () { + reportError('ERROR: Loading template app(' + template + ') failed!'); + }); + } else { + if (NanoTemplate.templateExists('app')) { + $("#uiApp").html(NanoTemplate.parse('app', data)); + } + } + } + } catch(error) { + reportError('ERROR: An error occurred while rendering the UI: ' + error.message); + return; + } +} \ No newline at end of file diff --git a/nano/scripts/nano/nano_template.js b/nano/scripts/nano/nano_template.js index 7350e62d48d..e37724f1bb4 100644 --- a/nano/scripts/nano/nano_template.js +++ b/nano/scripts/nano/nano_template.js @@ -87,6 +87,9 @@ var NanoTemplate = function () { templateExists: function (key) { return _templates.hasOwnProperty(key); }, + resetTemplate: function (key) { + _compiledTemplates[key] = null; + }, parse: function (templateKey, data) { if (!_compiledTemplates.hasOwnProperty(templateKey) || !_compiledTemplates[templateKey]) { if (!_templates.hasOwnProperty(templateKey)) { diff --git a/nano/styles/_color.less b/nano/styles/_color.less index 6194a96ac2b..68fc1d89c5b 100644 --- a/nano/styles/_color.less +++ b/nano/styles/_color.less @@ -1,9 +1,4 @@ -@good-color: #4f7529; -@average-color: #cd6500; -@bad-color: #ee0000; - -@highlight-color: #8BA5C4; -@dark-color: #272727; +@import "_config"; .white { color: white; diff --git a/nano/styles/_config.less b/nano/styles/_config.less index a44ef50fd54..dffcc37331c 100644 --- a/nano/styles/_config.less +++ b/nano/styles/_config.less @@ -4,4 +4,12 @@ // Body Colors @background-start: #2a2a2a; -@background-end: #202020; \ No newline at end of file +@background-end: #202020; + +// Element Colors +@good-color: #4f7529; +@average-color: #cd6500; +@bad-color: #ee0000; + +@highlight-color: #8BA5C4; +@dark-color: #272727; \ No newline at end of file diff --git a/nano/styles/_misc.less b/nano/styles/_misc.less index 55f8216b3b6..fe7646062b2 100644 --- a/nano/styles/_misc.less +++ b/nano/styles/_misc.less @@ -74,6 +74,14 @@ div.notice { .pdalink { float: left; white-space: nowrap; + cursor: default !important; + + &.disabled { + background: none; + border: none; + color: #999; + text-align: left; + } } .pdanote { @@ -81,6 +89,50 @@ div.notice { font-weight: bold; } +.item.mainmenu { + padding-bottom: 0.5em; +} + +div.clock { + color: white; + font-weight: bold; + float: right; + padding-right: 2em; +} + +#pdaFooter { + position: fixed; + left: 0; + bottom: 0; + width: 100%; + background: @dark-color; +} + +.pdaFooterButton { + width: 33%; + padding: 0.5em 0; + font-size: 200%; + border: none; + background: none; + color: #fff; + + &:hover { + background: #507aac; + } + + &.disabled { + background: none !important; + color: #555 !important; + } + + .uiLinkPendingIcon { + position: absolute; + width: 33%; + background-repeat: no-repeat; + background-position: center; + } +} + /* DNA Modifier styling */ .dnaBlock { float: left; diff --git a/nano/styles/_native.less b/nano/styles/_native.less index 8114d75133c..3061b54c72c 100644 --- a/nano/styles/_native.less +++ b/nano/styles/_native.less @@ -1,7 +1,7 @@ @import "_config"; body { - background: #272727; + background: @dark-color; color: #ffffff; font-family: @font; font-size: @fontsize; diff --git a/nano/templates/pda.tmpl b/nano/templates/pda.tmpl index 54ab77a9be6..3d11ee0a6f8 100644 --- a/nano/templates/pda.tmpl +++ b/nano/templates/pda.tmpl @@ -1,4 +1,3 @@ - - {{:helper.link('Close', 'gear', {'choice' : "Close"}, null, 'pdalink fixedLeft')}} - {{if data.idInserted}} {{:helper.link('Update PDA Info', 'eject', {'choice' : "UpdateInfo"}, null, 'pdalink fixedLeftWide')}} {{/if}} - {{if data.mode != 0}} {{:helper.link('Return', 'arrow-left', {'choice' : "Return"}, null, 'pdalink fixedLeft')}} {{/if}} - {{:helper.link('Toggle R.E.T.R.O. mode', 'gear', {'choice': "Retro"}, null, 'floatRight')}} +
+ {{if data.idInserted}} + {{:helper.link(data.idLink, 'eject', {'choice' : "Authenticate"}, null, 'pdalink fixedLeftWide')}} + {{/if}} + {{if data.cartridge_name}} + {{:helper.link(data.cartridge_name, 'eject', {'choice' : "Eject"}, null, 'pdalink fixedLeftWidest')}} + {{/if}} + {{:helper.link('Toggle R.E.T.R.O. mode', 'gear', {'choice': "Retro"}, null, 'pdalink fixedLeftWide')}} +
+
+ {{:data.stationTime}}
-
-
-
- Station Time: -
-
- {{:data.stationTime}} -
+ + {{if data.app}} +

 {{:data.app.name}}

+
+
 
+ {{/if}} + +
+ {{:helper.link("", 'undo', {'choice' : "Back"}, data.app.has_back ? null : 'disabled', 'link pdaFooterButton')}} + {{:helper.link("", 'home', {'choice' : "Home"}, data.app.is_home ? 'disabled' : null, 'link pdaFooterButton')}}
-
- - - {{if data.mode == 0}} -
-
- Owner: -
-
- {{:data.owner}}, {{:data.ownjob}} -
-
-
-
-
- ID: -
-
- {{:helper.link(data.idLink, 'eject', {'choice' : "Authenticate"}, data.idInserted ? null : 'disabled', data.idInserted ? 'link fixedLeftWidest' : 'link fixedLeft')}} -
-
-
-
-
- Cartridge: -
-
- {{if data.cart_loaded==1}} - {{:helper.link(data.cartridge.name, 'eject', {'choice' : "Eject"},null,null)}} - {{else}} - {{:helper.link('None', 'eject', {'choice' : "Eject"},'disabled',null)}} - {{/if}} -
-
-
-

Functions

-
-
-
- General: -
-
- {{:helper.link('Notekeeper', 'sticky-note', {'choice' : "1"}, null, 'pdalink fixedLeftWide')}} - {{:helper.link('Messenger', data.newMessage ? 'envelope' : 'envelope-o', {'choice' : "2"}, null, 'pdalink fixedLeftWide')}} - {{:helper.link('Crew Manifest', 'user', {'choice' : "41"}, null, 'pdalink fixedLeftWide')}} -
-
-
- {{if data.cartridge}} - {{if data.cartridge.access.access_clown == 1}} -
-
- Clown: -
-
- {{:helper.link('Honk Synthesizer', 'gear', {'choice' : "Honk"}, null, 'pdalink fixedLeftWide')}} -
-
-
- {{/if}} - {{if data.cartridge.access.access_engine == 1}} -
-
- Engineering: -
-
- {{:helper.link('Power Monitor', 'exclamation-triangle', {'choice' : "43"}, null, 'pdalink fixedLeftWide')}} -
-
-
- {{/if}} - {{if data.cartridge.access.access_medical == 1}} -
-
- Medical: -
-
- {{:helper.link('Medical Records', 'gear', {'choice' : "44"}, null, 'pdalink fixedLeftWide')}} - {{:helper.link(data.scanmode == 1 ? 'Disable Med Scanner' : 'Enable Med Scanner', 'gear', {'choice' : "Medical Scan"}, null , 'pdalink fixedLeftWide')}} -
-
-
- {{/if}} - {{if data.cartridge.access.access_security == 1}} -
-
- Security: -
-
- {{:helper.link('Security Records', 'gear', {'choice' : "45"}, null, 'pdalink fixedLeftWide')}} - {{if data.cartridge.radio ==1}} {{:helper.link('Security Bot Access', 'gear', {'choice' : "46"}, null, 'pdalink fixedLeftWide')}} {{/if}} -
-
-
-
- {{/if}} - {{if data.cartridge.access.access_quartermaster == 1}} -
-
- Quartermaster: -
-
- {{:helper.link('Supply Records', 'gear', {'choice' : "47"}, null, 'pdalink fixedLeftWide')}} - {{if data.cartridge.radio == 3}} {{:helper.link('Delivery Bot Control', 'gear', {'choice' : "48"}, null, 'pdalink fixedLeftWide')}} {{/if}} -
-
-
-
- {{/if}} - {{/if}} -
-
-
- Utilities: -
-
- {{if data.cartridge}} - {{if data.cartridge.access.access_status_display == 1}} - {{:helper.link('Status Display', 'gear', {'choice' : "42"}, null, 'pdalink fixedLeftWide')}} - {{/if}} - {{if data.cartridge.access.access_janitor==1}} - {{:helper.link('Custodial Locator', 'gear', {'choice' : "49"}, null, 'pdalink fixedLeftWide')}} - {{/if}} - {{if data.cartridge.radio == 2}} - {{:helper.link('Signaler System', 'gear', {'choice' : "40"}, null, 'pdalink fixedLeftWide')}} - {{/if}} - {{if data.cartridge.access.access_reagent_scanner==1}} - {{:helper.link(data.scanmode == 3 ? 'Disable Reagent Scanner' : 'Enable Reagent Scanner', 'gear', {'choice' : "Reagent Scan"}, null, 'pdalink fixedLeftWider')}} - {{/if}} - {{if data.cartridge.access.access_engine==1}} - {{:helper.link(data.scanmode == 4 ? 'Disable Halogen Counter' : 'Enable Halogen Counter', 'gear', {'choice' : "Halogen Counter"}, null, 'pdalink fixedLeftWider')}} - {{/if}} - {{if data.cartridge.access.access_atmos==1}} - {{:helper.link(data.scanmode == 5 ? 'Disable Gas Scanner' : 'Enable Gas Scanner', 'gear', {'choice' : "Gas Scan"}, null, 'pdalink fixedLeftWide')}} - {{/if}} - {{if data.cartridge.access.access_remote_door==1}} - {{:helper.link('Toggle Door', 'gear', {'choice' : "Toggle Door"}, null, 'pdalink fixedLeftWide')}} - {{/if}} - {{/if}} - {{:helper.link('Atmospheric Scan', 'gear', {'choice' : "3"}, null, 'pdalink fixedLeftWide')}} - {{:helper.link(data.fon==1 ? 'Disable Flashlight' : 'Enable Flashlight', 'lightbulb-o', {'choice' : "Light"}, null,'pdalink fixedLeftWide')}} -
-
- {{if data.pai}} -
-
- PAI Utilities: -
-
- {{:helper.link('Configuration', 'gear', {'choice' : "pai", 'option' : "1"}, null, 'pdalink fixedLeft')}} - {{:helper.link('Eject pAI', 'eject', {'choice' : "pai", 'option' : "2"}, null, 'pdalink fixedLeft')}} -
-
- {{/if}} - - - {{else data.mode == 1}} -
-
- Notes: -
-
-
-
-
- {{:data.note}} -
-
-
-
-
- {{:helper.link('Edit Notes', 'gear', {'choice' : "Edit"}, null, 'pdalink fixedLeft')}} -
-
- - - {{else data.mode == 2}} -

SpaceMessenger V4.0.1

-
-
- Messenger 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 ? '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('Delete all Conversations', 'trash', {'choice' : "Clear", 'option' : "All"}, null, 'pdalink fixedLeftWider')}} -
-
- {{if data.toff == 0}} -

- {{if data.cartridge}} - {{if data.cartridge.charges}} -
- {{:data.cartridge.charges}} - {{if data.cartridge.access.access_detonate_pda}} detonation charges left. {{/if}} - {{if data.cartridge.access.access_clown || data.cartridge.access.access_mime}} viral files left. {{/if}} - -

-
- {{/if}} - {{/if}} - - {{if data.pda_count == 0}} - No other PDAS located - {{else}} -

Current Conversations

- {{for data.convopdas}} -
- {{:helper.link(value.Name, 'arrow-circle-down', {'choice' : "Select Conversation", 'convo' : value.Reference } , null, 'pdalink')}} - {{if data.cartridge}} - {{if data.cartridge.access.access_detonate_pda && value.Detonate}} - {{:helper.link('*Detonate*', 'exclamation-circle', {'choice' : "Detonate", 'target' : value.Reference}, null, 'pdalink fixedLeft')}} - {{/if}} - {{if data.cartridge.access.access_clown}} - {{:helper.link('*Send Virus*', 'star', {'choice' : "Send Honk", 'target' : value.Reference}, null, 'pdalink fixedLeft')}} - {{/if}} - {{if data.cartridge.access.access_mime}} - {{:helper.link('*Send Virus*', 'arrow-circle-down', {'choice' : "Send Silence", 'target' : value.Reference}, null, 'pdalink fixedLeft')}} - {{/if}} - {{/if}} -
- {{/for}} -

Other PDAs

- {{for data.pdas}} -
- {{:helper.link(value.Name, 'arrow-circle-down', {'choice' : "Message", 'target' : value.Reference}, null, 'pdalink')}} - {{if data.cartridge}} - {{if data.cartridge.access.access_detonate_pda && value.Detonate}} {{:helper.link('*Detonate*', 'exclamation-circle', {'choice' : "Detonate", 'target' : value.Reference}, null, 'pdalink fixedLeft')}} {{/if}} - {{if data.cartridge.access.access_clown}} {{:helper.link('*Send Virus*', 'star', {'choice' : "Send Honk", 'target' : value.Reference}, null, 'pdalink fixedLeft')}} {{/if}} - {{if data.cartridge.access.access_mime}} {{:helper.link('*Send Virus*', 'arrow-circle-down', {'choice' : "Send Silence", 'target' : value.Reference}, null, 'pdalink fixedLeft')}} {{/if}} - {{/if}} -
- {{/for}} - {{/if}} - {{/if}} - - - {{else data.mode == 21}} -

SpaceMessenger V4.0.1

-
-
- Messenger Functions: -
-
- {{:helper.link('Delete Conversation', 'trash', {'choice' : "Clear", 'option' : "Convo"}, null, 'pdalink fixedLeftWide')}} -
-
-
-
-

Conversation with: {{:data.convo_name}} ({{:data.convo_job}})

-
-
-
- {{for data.messages}} - {{if data.active_conversation == value.target}} - {{if value.sent==0}} - Them: {{:value.message}}
- {{else}} - You: {{:value.message}}
- {{/if}} - {{/if}} - {{/for}} -
-
-
- {{:helper.link('Reply', 'comment', {'choice' : "Message", 'target': data.active_conversation}, null, 'pdalink fixedLeft')}} - - - {{else data.mode== 41}} -
-
- {{if data.manifest.heads}} - - {{for data.manifest["heads"]}} - {{if value.rank == "Captain"}} - - {{else}} - - {{/if}} - {{/for}} - {{/if}} - {{if data.manifest.sec}} - - {{for data.manifest["sec"]}} - {{if value.rank == "Head of Security"}} - - {{else}} - - {{/if}} - {{/for}} - {{/if}} - {{if data.manifest.eng}} - - {{for data.manifest["eng"]}} - {{if value.rank == "Chief Engineer"}} - - {{else}} - - {{/if}} - {{/for}} - {{/if}} - {{if data.manifest.med}} - - {{for data.manifest["med"]}} - {{if value.rank == "Chief Medical Officer"}} - - {{else}} - - {{/if}} - {{/for}} - {{/if}} - {{if data.manifest.sci}} - - {{for data.manifest["sci"]}} - {{if value.rank == "Research Director"}} - - {{else}} - - {{/if}} - {{/for}} - {{/if}} - {{if data.manifest.ser}} - - {{for data.manifest["ser"]}} - {{if value.rank == "Head of Personnel"}} - - {{else}} - - {{/if}} - {{/for}} - {{/if}} - {{if data.manifest.sup}} - - {{for data.manifest["sup"]}} - {{if value.rank == "Head of Personnel"}} - - {{else value.rank == "Quartermaster"}} - - {{else}} - - {{/if}} - {{/for}} - {{/if}} - {{if data.manifest.civ}} - - {{for data.manifest["civ"]}} - {{if value.rank == "Head of Personnel"}} - - {{else}} - - {{/if}} - {{/for}} - {{/if}} - {{if data.manifest.misc}} - - {{for data.manifest["misc"]}} - - {{/for}} - {{/if}} -
Command
{{:value.name}}{{:value.rank}}{{:value.active}}
{{:value.name}}{{:value.rank}}{{:value.active}}
Security
{{:value.name}}{{:value.rank}}{{:value.active}}
{{:value.name}}{{:value.rank}}{{:value.active}}
Engineering
{{:value.name}}{{:value.rank}}{{:value.active}}
{{:value.name}}{{:value.rank}}{{:value.active}}
Medical
{{:value.name}}{{:value.rank}}{{:value.active}}
{{:value.name}}{{:value.rank}}{{:value.active}}
Science
{{:value.name}}{{:value.rank}}{{:value.active}}
{{:value.name}}{{:value.rank}}{{:value.active}}
Service
{{:value.name}}{{:value.rank}}{{:value.active}}
{{:value.name}}{{:value.rank}}{{:value.active}}
Supply
{{:value.name}}{{:value.rank}}{{:value.active}}
{{:value.name}}{{:value.rank}}{{:value.active}}
{{:value.name}}{{:value.rank}}{{:value.active}}
Civilian
{{:value.name}}{{:value.rank}}{{:value.active}}
{{:value.name}}{{:value.rank}}{{:value.active}}
Misc
{{:value.name}}{{:value.rank}}{{:value.active}}
-
- - - {{else data.mode == 3}} -

Atmospheric Scan

-
-
- {{if data.aircontents.reading == 1}} -
- Pressure: -
-
- {{:helper.string('{1} kPa', data.aircontents.pressure < 80 || data.aircontents.pressure > 120 ? 'bad' : data.aircontents.pressure < 95 || data.aircontents.pressure > 110 ? 'average' : 'good' , data.aircontents.pressure)}} -
-
- Temperature: -
-
- {{:helper.string('{1} °C', data.aircontents.temp < 5 || data.aircontents.temp > 35 ? 'bad' : data.aircontents.temp < 15 || data.aircontents.temp > 25 ? 'average' : 'good' , data.aircontents.temp)}} -
-
-
- Oxygen: -
-
- {{:helper.string('{1}%', data.aircontents.oxygen < 17 ? 'bad' : data.aircontents.oxygen < 19 ? 'average' : 'good' , data.aircontents.oxygen)}} -
-
- Nitrogen: -
-
- {{:helper.string('{1}%', data.aircontents.nitrogen > 82 ? 'bad' : data.aircontents.nitrogen > 80 ? 'average' : 'good' , data.aircontents.nitrogen)}} -
-
- Carbon Dioxide: -
-
- {{:helper.string('{1}%', data.aircontents.carbon_dioxide > 5 ? 'bad' : 'good' , data.aircontents.carbon_dioxide)}} -
-
- Plasma: -
-
- {{:helper.string('{1}%', data.aircontents.plasma > 0 ? 'bad' : 'good' , data.aircontents.plasma)}} - -
- {{if data.aircontents.other > 0}} -
- Unknown: -
-
- {{:data.aircontents.other}}% -
- {{/if}} - {{else}} -
- Unable to get air reading -
- {{/if}} -
-
- - - {{else data.mode == 40}} -

Remote Signaling System

-
-
- Frequency: -
-
- {{:data.records.signal_freq}} -
-   - {{:helper.link('-1', null, {'cartmenu' : "1", 'choice' : "Signal Frequency", 'sfreq' : "-10"}, null, null)}}  - {{:helper.link('-.2', null, {'cartmenu' : "1", 'choice' : "Signal Frequency", 'sfreq' : "-2"}, null, null)}}  - - {{:helper.link('+.2', null, {'cartmenu' : "1", 'choice' : "Signal Frequency", 'sfreq' : "2"}, null, null)}}  - {{:helper.link('+1', null, {'cartmenu' : "1", 'choice' : "Signal Frequency", 'sfreq' : "10"}, null, null)}} -
-
-
-
-
-
- Code: -
-
- - {{:data.records.signal_code}}
-
- {{:helper.link('-5', null, {'cartmenu' : "1", 'choice' : "Signal Code", 'scode' : "-5"}, null, null)}} - {{:helper.link('-1', null, {'cartmenu' : "1", 'choice' : "Signal Code", 'scode' : "-1"}, null, null)}} - {{:helper.link('+1', null, {'cartmenu' : "1", 'choice' : "Signal Code", 'scode' : "1"}, null, null)}} - {{:helper.link('+5', null, {'cartmenu' : "1", 'choice' : "Signal Code", 'scode' : "5"}, null, null)}} -
-
-
- {{:helper.link('Send Signal', 'exclamation-circle', {'cartmenu' : "1", 'choice' : "Send Signal"}, null, null)}} -
- - - {{else data.mode == 42}} -

Station Status Displays Interlink

-
-
- Code: -
-
- {{:helper.link('Clear', 'trash', {'cartmenu' : "1", 'choice' : "Status", 'statdisp' : "blank"}, null, null)}} - {{:helper.link('Shuttle ETA', 'gear', {'cartmenu' : "1", 'choice' : "Status",'statdisp' : "shuttle"}, null, null)}} - {{:helper.link('Message', 'gear', {'cartmenu' : "1", 'choice' : "Status",'statdisp' : "message"}, null, null)}} -
-
-
-
-
- Message line 1 -
-
- {{:helper.link(data.records.message1 + ' (set)', 'pencil', {'cartmenu' : "1", 'choice' : "Status",'statdisp' : "setmsg1"}, null, null)}} -
-
-
-
- Message line 2 -
-
- {{:helper.link(data.records.message2 + ' (set)', 'pencil', {'cartmenu' : "1", 'choice' : "Status",'statdisp' : "setmsg2"}, null, null)}} -
-
- -
-
-
- ALERT!: -
-
- {{:helper.link('None', 'bell', {'cartmenu' : "1", 'choice' : "Status",'statdisp' : "alert", 'exclamation-triangle' : "default"}, null, null)}} - {{:helper.link('Red Alert', 'bell', {'cartmenu' : "1", 'choice' : "Status",'statdisp' : "alert", 'exclamation-triangle' : "redalert"}, null, null)}} - {{:helper.link('Lockdown', 'exclamation-circle', {'cartmenu' : "1", 'choice' : "Status",'statdisp' : "alert", 'exclamation-triangle' : "lockdown"}, null, null)}} - {{:helper.link('Biohazard', 'exclamation-circle', {'cartmenu' : "1", 'choice' : "Status",'statdisp' : "alert", 'exclamation-triangle' : "biohazard"}, null, null)}} -
-
- - - {{else data.mode == 43}} -

Station Power Monitors

-
- Select a power monitor: -
- {{for data.records.powermonitors}} -
- {{:helper.link(value.Name, 'exclamation-circle', {'cartmenu' : "1", 'choice' : "Power Select",'target' : value.ref}, null, null)}} -
- {{/for}} - - - {{else data.mode == 433}} -

Powernet Status

- {{if data.records.powerconnected == 1}} -
-
- Total Power: -
-
- {{:data.records.poweravail}} W -
-
-
-
- Total Load: -
-
- {{:data.records.powerload}} W -
-
-
-
- Total Demand: -
-
- {{:data.records.powerdemand}} W -
-
-
- - - {{for data.records.apcs}} - - {{:helper.string('', value.Equipment == "On" || value.Equipment == "AOn" ? '#4f7529' : '#8f1414', value.Equipment)}} - {{:helper.string('', value.Lights == "On" || value.Lights == "AOn" ? '#4f7529' : '#8f1414', value.Lights)}} - {{:helper.string('', value.Environment == "On" || value.Environment == "AOn" ? '#4f7529' : '#8f1414', value.Environment)}} - {{:helper.string('', value.CellStatus == "F" ? '#4f7529' : value.CellStatus == "C" ? '#cd6500' : '#8f1414', value.CellStatus == "M" ? 'No Cell' : value.CellPct + '%', value.CellStatus == "M" ? '' : ' (' + value.CellStatus + ')')}} - - - {{/for}} -
AreaEquip.LightingEnviron.CellLoad
{{:value.Name}}{1}{1}{1}{1}{2}{{:value.Load}}W
-
- {{else}} - Power monitor not connected to net. - {{/if}} - - - - {{else data.mode == 44}} -

Medical Record List

-
- Select A record -
-
- {{for data.records.medical_records}} -
- {{:helper.link(value.Name, 'gear', {'cartmenu' : "1", 'choice' : "Medical Records",'target' : value.ref}, null, null)}} -
- {{/for}} - - - {{else data.mode == 441}} -

Medical Record

-
-
-
- {{if data.records.general_exists == 1}} - Name: {{:data.records.general.name}}
- Sex: {{:data.records.general.sex}}
- Species: {{:data.records.general.species}}
- Age: {{:data.records.general.age}}
- Rank: {{:data.records.general.rank}}
- Fingerprint: {{:data.records.general.fingerprint}}
- Physical Status: {{:data.records.general.p_stat}}
- Mental Status: {{:data.records.general.m_stat}}

- {{else}} - - General Record Lost!

-
- {{/if}} - {{if data.records.medical_exists == 1}} - Medical Data:
- Blood Type: {{:data.records.medical.b_type}}

- Minor Disabilities: {{:data.records.medical.mi_dis}}
- Details: {{:data.records.medical.mi_dis_d}}

- Major Disabilities: {{:data.records.medical.ma_dis}}
- Details: {{:data.records.medical.ma_dis_d}}

- Allergies: {{:data.records.medical.alg}}
- Details: {{:data.records.medical.alg_d}}

- Current Disease: {{:data.records.medical.cdi}}
- Details: {{:data.records.medical.alg_d}}

- Important Notes: {{:data.records.medical.notes}} - {{else}} - - Medical Record Lost! -
-
-
- {{/if}} -
-
-
- - - {{else data.mode == 45}} -

Security Record List

-
- Select A record -
-
- {{for data.records.security_records}} -
- {{:helper.link(value.Name, 'gear', {'cartmenu' : "1", 'choice' : "Security Records",'target' : value.ref}, null, null)}} -
- {{/for}} - - - {{else data.mode == 451}} -

Security Record

-
-
-
- {{if data.records.general_exists == 1}} - Name: {{:data.records.general.name}}
- Sex: {{:data.records.general.sex}}
- Species: {{:data.records.general.species}}
- Age: {{:data.records.general.age}}
- Rank: {{:data.records.general.rank}}
- Fingerprint: {{:data.records.general.fingerprint}}
- Physical Status: {{:data.records.general.p_stat}}
- Mental Status: {{:data.records.general.m_stat}}

- {{else}} - - General Record Lost!

-
- {{/if}} - {{if data.records.security_exists == 1}} - Security Data:
- Criminal Status: {{:data.records.security.criminal}}

- Minor Crimes: {{:data.records.security.mi_crim}}
- Details: {{:data.records.security.mi_crim_d}}

- Major Crimes: {{:data.records.security.ma_crim}}
- Details: {{:data.records.security.ma_crim_d}}

- Important Notes: {{:data.records.security.notes}} - {{else}} - - Security Record Lost!

-
- {{/if}} -
-
-
- - - {{else data.mode == 46}} -

Security Bot Control

- {{if data.records.beepsky.active == null || data.records.beepsky.active == 0}} - {{if data.records.beepsky.count == 0}} -

No bots found.

- {{else}} -
- Select A Bot. -
-
- {{for data.records.beepsky.bots}} -
- {{:helper.link(value.Name, 'gear', {'radiomenu' : "1", 'op' : "control",'bot' : value.ref}, null, null)}} (Location: {{:value.Location}}) -
- {{/for}} - {{/if}} -
- {{:helper.link('Scan for Bots','gear', {'radiomenu' : "1", 'op' : "scanbots"}, null, null)}} - {{else}} -

{{:data.records.beepsky.active}}

-

- {{if data.records.beepsky.botstatus.mode == -1}} -

Waiting for response...

- {{else}} -

Status:

-
-
-
- Location: -
-
- {{:data.records.beepsky.botstatus.loca}} -
-
-
-
- Mode: -
-
- - {{if data.records.beepsky.botstatus.mode ==0}} - Ready - {{else data.records.beepsky.botstatus.mode == 1}} - Apprehending target - {{else data.records.beepsky.botstatus.mode ==2 || data.records.beepsky.botstatus.mode == 3}} - Arresting target - {{else data.records.beepsky.botstatus.mode ==4}} - Starting patrol - {{else data.records.beepsky.botstatus.mode ==5}} - On Patrol - {{else data.records.beepsky.botstatus.mode ==6}} - Responding to summons - {{/if}} - -
-
-
- {{:helper.link('Stop Patrol', 'gear', {'radiomenu' : "1", 'op' : "stop"}, null, null)}} - {{:helper.link('Start Patrol', 'gear', {'radiomenu' : "1", 'op' : "go"}, null, null)}} - {{:helper.link('Summon Bot', 'gear', {'radiomenu' : "1", 'op' : "summon"}, null, null)}} -
- {{/if}} - {{:helper.link('Return to Bot list', 'gear', {'radiomenu' : "1", 'op' : "botlist"}, null, null)}} - {{/if}} - - - {{else data.mode == 47}} -

Supply Record Interlink

-
-
- Location: -
-
- - {{if data.records.supply.shuttle_moving}} - Moving to {{:data.records.supply.shuttle_loc}} - {{else}} - Shuttle at {{:data.records.supply.shuttle_loc}} - {{/if}} -
- {{:data.records.supply.shuttle_time}} -
-
-
-
-
-
- Current Approved Orders
- {{if data.records.supply.approved_count == 0}} - No current approved orders

- {{else}} - {{for data.records.supply.approved}} - #{{:value.Number}} - {{:value.Name}} approved by {{:value.OrderedBy}}
{{if value.Comment != ""}} {{:value.Comment}}
{{/if}}
- {{/for}} - {{/if}} -

- Current Requested Orders
- {{if data.records.supply.requests_count == 0}} - No current requested orders

- {{else}} - {{for data.records.supply.requests}} - #{{:value.Number}} - {{:value.Name}} requested by {{:value.OrderedBy}}
{{if value.Comment != ""}} {{:value.Comment}}
{{/if}}
- {{/for}} - {{/if}} -
-
-
- - - {{else data.mode == 48}} -

Mule Control

- {{if data.records.mulebot.active == null || data.records.mulebot.active == 0}} - {{if data.records.mulebot.count == 0}} -

No bots found.

- {{else}} -

Mule List

-
- Select A Mulebot -
-
- {{for data.records.mulebot.bots}} -
- {{:helper.link(value.Name, 'gear', {'radiomenu' : "1", 'op' : "control",'bot' : value.ref}, null, null)}} (Location: {{:value.Location}}) -
- {{/for}} - {{/if}} -
- {{:helper.link('Scan for Bots','gear', {'radiomenu' : "1", 'op' : "scanbots"}, null, null)}} - {{else}} - {{if data.records.mulebot.botstatus.mode == -1}} -

Waiting for response...

- {{else}} -

Status:

-
-
-
- Location: -
-
- {{:data.records.mulebot.botstatus.loca}} -
-
-
-
- Mode: -
-
- - {{if data.records.mulebot.botstatus.mode ==0}} - Ready - {{else data.records.mulebot.botstatus.mode == 1}} - Loading/Unloading - {{else data.records.mulebot.botstatus.mode ==2}} - Navigating to Delivery Location - {{else data.records.mulebot.botstatus.mode == 3}} - Navigating to Home - {{else data.records.mulebot.botstatus.mode ==4}} - Waiting for Clear Path - {{else data.records.mulebot.botstatus.mode ==5 || data.records.mulebot.botstatus.mode == 6}} - Calculating navigation Path - {{else data.records.mulebot.botstatus.mode ==7}} - Unable to locate destination - {{/if}} - -
-
-
-
- Current Load: -
-
- - {{:helper.link(data.records.mulebot.botstatus.load == null ? 'None (Unload)' : data.records.mulebot.botstatus.load + ' (Unload)', 'gear', {'radiomenu' : "1", 'op' : "unload"},data.records.mulebot.botstatus.load == null ? 'disabled' : null, null)}} - -
-
-
-
- Power: -
-
- - {{:data.records.mulebot.botstatus.powr}}% - -
-
-
-
- Destination: -
-
- {{:helper.link(data.records.mulebot.botstatus.dest == null || data.records.mulebot.botstatus.dest == "" ? 'None (Set)': data.records.mulebot.botstatus.dest+ ' (Set)', 'gear', {'radiomenu' : "1", 'op' : "setdest"}, null, null)}} -
-
-
-
- Home: -
-
- {{if data.records.mulebot.botstatus.home == null}} None {{else}} {{:data.records.mulebot.botstatus.home}} {{/if}} -
-
-
-
- Auto Return: -
-
- {{:helper.link(data.records.mulebot.botstatus.retn == 1 ? 'ON' : 'OFF', 'gear', {'radiomenu' : "1", 'op' : data.records.mulebot.botstatus.retn==1 ? "retoff" : "reton"}, null, null)}} -
-
-
-
- Auto Pickup: -
-
- {{:helper.link(data.records.mulebot.botstatus.pick==1? 'ON' : 'OFF', 'gear', {'radiomenu' : "1", 'op' : data.records.mulebot.botstatus.pick==1 ? "pickoff" : "pickon"}, null, null)}} -
-
-
-
- Functions: -
-
- {{:helper.link('Stop', 'gear', {'radiomenu' : "1", 'op' : "stop"}, null, null)}} - {{:helper.link('Proceed', 'gear', {'radiomenu' : "1", 'op' : "go"}, null, null)}} - {{:helper.link('Return Home', 'gear', {'radiomenu' : "1", 'op' : "home"}, null, null)}} -
-
-

- {{:helper.link('Return to Bot list', 'gear', {'radiomenu' : "1", 'op' : "botlist"}, null, null)}} - {{/if}} - {{/if}} - - - {{else data.mode == 49}} -

Janatorial Supplies Locator

-
- Current Location: - {{if data.records.janitor.user_loc.x == 0}} - Unknown - {{else}} - {{:data.records.janitor.user_loc.x}} / {{:data.records.janitor.user_loc.y}} - {{/if}} -
-
- {{for data.records.janitor.mops}} - {{if value.x==0}} - Unable to locate Mop - {{else}} - Mop Location: - ({{:value.x}} / {{:value.y}}) - {{:value.dir}} - Status: {{:value.status}}
- {{/if}} - {{/for}} -
-
- {{for data.records.janitor.buckets}} - {{if value.x==0}} - Unable to locate Water Buckets - {{else}} - Water Buckets Location: - ({{:value.x}} / {{:value.y}}) - {{:value.dir}} - Water Level: {{:value.status}}
- {{/if}} - {{/for}} -
-
- {{for data.records.janitor.cleanbots}} - {{if value.x==0}} - Unable to locate Clean Bots - {{else}} - Clean Bots Location: - ({{:value.x}} / {{:value.y}}) - {{:value.dir}} - Status: {{:value.status}}
- {{/if}} - {{/for}} -
-
- {{for data.records.janitor.carts}} - {{if value.x==0}} - Unable to locate Janitorial Cart - {{else}} - Janitorial cart Location: - ({{:value.x}} / {{:value.y}}) - {{:value.dir}} - Status: {{:value.status}}
- {{/if}} - {{/for}} -
- {{/if}} {{else}}







No Owner information found, please swipe ID
-{{/if}} - +{{/if}} \ No newline at end of file diff --git a/nano/templates/pda_atmos_scan.tmpl b/nano/templates/pda_atmos_scan.tmpl new file mode 100644 index 00000000000..80fa3838995 --- /dev/null +++ b/nano/templates/pda_atmos_scan.tmpl @@ -0,0 +1,60 @@ + +
+
+ {{if data.aircontents.reading == 1}} +
+ Pressure: +
+
+ {{:helper.string('{1} kPa', data.aircontents.pressure < 80 || data.aircontents.pressure > 120 ? 'bad' : data.aircontents.pressure < 95 || data.aircontents.pressure > 110 ? 'average' : 'good' , data.aircontents.pressure)}} +
+
+ Temperature: +
+
+ {{:helper.string('{1} °C', data.aircontents.temp < 5 || data.aircontents.temp > 35 ? 'bad' : data.aircontents.temp < 15 || data.aircontents.temp > 25 ? 'average' : 'good' , data.aircontents.temp)}} +
+
+
+ Oxygen: +
+
+ {{:helper.string('{1}%', data.aircontents.oxygen < 17 ? 'bad' : data.aircontents.oxygen < 19 ? 'average' : 'good' , data.aircontents.oxygen)}} +
+
+ Nitrogen: +
+
+ {{:helper.string('{1}%', data.aircontents.nitrogen > 82 ? 'bad' : data.aircontents.nitrogen > 80 ? 'average' : 'good' , data.aircontents.nitrogen)}} +
+
+ Carbon Dioxide: +
+
+ {{:helper.string('{1}%', data.aircontents.carbon_dioxide > 5 ? 'bad' : 'good' , data.aircontents.carbon_dioxide)}} +
+
+ Plasma: +
+
+ {{:helper.string('{1}%', data.aircontents.plasma > 0 ? 'bad' : 'good' , data.aircontents.plasma)}} + +
+ {{if data.aircontents.other > 0}} +
+ Unknown: +
+
+ {{:data.aircontents.other}}% +
+ {{/if}} + {{else}} +
+ Unable to get air reading +
+ {{/if}} +
+
\ No newline at end of file diff --git a/nano/templates/pda_janitor.tmpl b/nano/templates/pda_janitor.tmpl new file mode 100644 index 00000000000..a2fd282ad3f --- /dev/null +++ b/nano/templates/pda_janitor.tmpl @@ -0,0 +1,50 @@ +
+
+ Current Location: + {{if data.janitor.user_loc.x == 0}} + Unknown + {{else}} + {{:data.janitor.user_loc.x}} / {{:data.janitor.user_loc.y}} + {{/if}} +
+
+ {{for data.janitor.mops}} + {{if value.x==0}} + Unable to locate Mop + {{else}} + Mop Location: + ({{:value.x}} / {{:value.y}}) - {{:value.dir}} - Status: {{:value.status}}
+ {{/if}} + {{/for}} +
+
+ {{for data.janitor.buckets}} + {{if value.x==0}} + Unable to locate Water Buckets + {{else}} + Water Buckets Location: + ({{:value.x}} / {{:value.y}}) - {{:value.dir}} - Water Level: {{:value.status}}
+ {{/if}} + {{/for}} +
+
+ {{for data.janitor.cleanbots}} + {{if value.x==0}} + Unable to locate Clean Bots + {{else}} + Clean Bots Location: + ({{:value.x}} / {{:value.y}}) - {{:value.dir}} - Status: {{:value.status}}
+ {{/if}} + {{/for}} +
+
+ {{for data.janitor.carts}} + {{if value.x==0}} + Unable to locate Janitorial Cart + {{else}} + Janitorial cart Location: + ({{:value.x}} / {{:value.y}}) - {{:value.dir}} - Status: {{:value.status}}
+ {{/if}} + {{/for}} +
+
\ No newline at end of file diff --git a/nano/templates/pda_main_menu.tmpl b/nano/templates/pda_main_menu.tmpl new file mode 100644 index 00000000000..680e4a8fa75 --- /dev/null +++ b/nano/templates/pda_main_menu.tmpl @@ -0,0 +1,48 @@ + +
+
+ Owner: +
+
+ {{:data.owner}}, {{:data.ownjob}} +
+
+
+
+ ID: +
+
+ {{:helper.link('Update PDA Info', 'refresh', {'choice' : "UpdateInfo"}, data.idInserted ? null : 'disabled', 'pdalink fixedLeftWide')}} +
+
+ +
+

Functions

+
+{{for data.categories : cat : i}} + +{{/for}} + +{{if data.pai}} +
+
+ PAI Utilities: +
+
+ {{:helper.link('Configuration', 'gear', {'choice' : "pai", 'option' : "1"}, null, 'pdalink fixedLeft')}} + {{:helper.link('Eject pAI', 'eject', {'choice' : "pai", 'option' : "2"}, null, 'pdalink fixedLeft')}} +
+
+{{/if}} \ No newline at end of file diff --git a/nano/templates/pda_manifest.tmpl b/nano/templates/pda_manifest.tmpl new file mode 100644 index 00000000000..ef9e91a088f --- /dev/null +++ b/nano/templates/pda_manifest.tmpl @@ -0,0 +1,96 @@ + +
+
+ {{if data.manifest.heads}} + + {{for data.manifest["heads"]}} + {{if value.rank == "Captain"}} + + {{else}} + + {{/if}} + {{/for}} + {{/if}} + {{if data.manifest.sec}} + + {{for data.manifest["sec"]}} + {{if value.rank == "Head of Security"}} + + {{else}} + + {{/if}} + {{/for}} + {{/if}} + {{if data.manifest.eng}} + + {{for data.manifest["eng"]}} + {{if value.rank == "Chief Engineer"}} + + {{else}} + + {{/if}} + {{/for}} + {{/if}} + {{if data.manifest.med}} + + {{for data.manifest["med"]}} + {{if value.rank == "Chief Medical Officer"}} + + {{else}} + + {{/if}} + {{/for}} + {{/if}} + {{if data.manifest.sci}} + + {{for data.manifest["sci"]}} + {{if value.rank == "Research Director"}} + + {{else}} + + {{/if}} + {{/for}} + {{/if}} + {{if data.manifest.ser}} + + {{for data.manifest["ser"]}} + {{if value.rank == "Head of Personnel"}} + + {{else}} + + {{/if}} + {{/for}} + {{/if}} + {{if data.manifest.sup}} + + {{for data.manifest["sup"]}} + {{if value.rank == "Head of Personnel"}} + + {{else value.rank == "Quartermaster"}} + + {{else}} + + {{/if}} + {{/for}} + {{/if}} + {{if data.manifest.civ}} + + {{for data.manifest["civ"]}} + {{if value.rank == "Head of Personnel"}} + + {{else}} + + {{/if}} + {{/for}} + {{/if}} + {{if data.manifest.misc}} + + {{for data.manifest["misc"]}} + + {{/for}} + {{/if}} +
Command
{{:value.name}}{{:value.rank}}{{:value.active}}
{{:value.name}}{{:value.rank}}{{:value.active}}
Security
{{:value.name}}{{:value.rank}}{{:value.active}}
{{:value.name}}{{:value.rank}}{{:value.active}}
Engineering
{{:value.name}}{{:value.rank}}{{:value.active}}
{{:value.name}}{{:value.rank}}{{:value.active}}
Medical
{{:value.name}}{{:value.rank}}{{:value.active}}
{{:value.name}}{{:value.rank}}{{:value.active}}
Science
{{:value.name}}{{:value.rank}}{{:value.active}}
{{:value.name}}{{:value.rank}}{{:value.active}}
Service
{{:value.name}}{{:value.rank}}{{:value.active}}
{{:value.name}}{{:value.rank}}{{:value.active}}
Supply
{{:value.name}}{{:value.rank}}{{:value.active}}
{{:value.name}}{{:value.rank}}{{:value.active}}
{{:value.name}}{{:value.rank}}{{:value.active}}
Civilian
{{:value.name}}{{:value.rank}}{{:value.active}}
{{:value.name}}{{:value.rank}}{{:value.active}}
Misc
{{:value.name}}{{:value.rank}}{{:value.active}}
+
\ No newline at end of file diff --git a/nano/templates/pda_medical.tmpl b/nano/templates/pda_medical.tmpl new file mode 100644 index 00000000000..777fb91f4b8 --- /dev/null +++ b/nano/templates/pda_medical.tmpl @@ -0,0 +1,54 @@ +{{if !data.records}} +
+
Select a record:
+
+ {{for data.recordsList}} +
+ {{:helper.link(value.Name, 'user', {'choice' : "Records", 'target' : value.ref}, null, 'pdalink fixedLeftWidest')}} +
+ {{empty}} +
+ No records found. +
+ {{/for}} +{{else}} +
+
+
+ {{if data.records.general}} + Name: {{:data.records.general.name}}
+ Sex: {{:data.records.general.sex}}
+ Species: {{:data.records.general.species}}
+ Age: {{:data.records.general.age}}
+ Rank: {{:data.records.general.rank}}
+ Fingerprint: {{:data.records.general.fingerprint}}
+ Physical Status: {{:data.records.general.p_stat}}
+ Mental Status: {{:data.records.general.m_stat}}

+ {{else}} + + General Record Lost!

+
+ {{/if}} + {{if data.records.medical}} +
+
Medical Data:
+
+ Blood Type: {{:data.records.medical.b_type}}

+ Minor Disabilities: {{:data.records.medical.mi_dis}}
+ Details: {{:data.records.medical.mi_dis_d}}

+ Major Disabilities: {{:data.records.medical.ma_dis}}
+ Details: {{:data.records.medical.ma_dis_d}}

+ Allergies: {{:data.records.medical.alg}}
+ Details: {{:data.records.medical.alg_d}}

+ Current Disease: {{:data.records.medical.cdi}}
+ Details: {{:data.records.medical.alg_d}}

+ Important Notes: {{:data.records.medical.notes}} + {{else}} + + Medical Record Lost! + + {{/if}} +
+
+
+{{/if}} \ No newline at end of file diff --git a/nano/templates/pda_messenger.tmpl b/nano/templates/pda_messenger.tmpl new file mode 100644 index 00000000000..633ae7d4691 --- /dev/null +++ b/nano/templates/pda_messenger.tmpl @@ -0,0 +1,81 @@ + +{{if data.active_conversation}} +
+
+ Messenger Functions: +
+
+ {{:helper.link('Delete Conversation', 'trash', {'choice' : "Clear", 'option' : "Convo"}, null, 'pdalink fixedLeftWide')}} +
+
+
+
+

Conversation with: {{:data.convo_name}} ({{:data.convo_job}})

+
+
+
+ {{for data.messages}} + {{if data.active_conversation == value.target}} + {{if value.sent==0}} + Them: {{:value.message}}
+ {{else}} + You: {{:value.message}}
+ {{/if}} + {{/if}} + {{/for}} +
+
+
+ {{:helper.link('Reply', 'comment', {'choice' : "Message", 'target': data.active_conversation}, null, 'pdalink fixedLeft')}} +{{else}} +
+
+ Messenger 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 ? '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('Delete all Conversations', 'trash', {'choice' : "Clear", 'option' : "All"}, null, 'pdalink fixedLeftWider')}} +
+
+ {{if data.toff == 0}} +
+ {{if data.charges}} +
+ {{:data.charges}} charges left. +

+
+ {{/if}} + + {{if data.pda_count == 0}} + No other PDAS located + {{else}} +

Current Conversations

+ {{for data.convopdas}} +
+ {{:helper.link(value.Name, 'arrow-circle-down', {'choice' : "Select Conversation", 'convo' : value.Reference } , null, 'pdalink')}} + {{if data.charges}} + {{for data.plugins : plugin : i}} + {{:helper.link(plugin.name, plugin.icon, {'choice' : "Messenger Plugin", 'plugin' : plugin.ref, 'target' : value.Reference}, null, 'pdalink fixedLeft')}} + {{/for}} + {{/if}} +
+ {{/for}} +

Other PDAs

+ {{for data.pdas}} +
+ {{:helper.link(value.Name, 'arrow-circle-down', {'choice' : "Message", 'target' : value.Reference}, null, 'pdalink')}} + {{if data.charges}} + {{for data.plugins : plugin : i}} + {{:helper.link(plugin.name, plugin.icon, {'choice' : "Messenger Plugin", 'plugin' : plugin.ref, 'target' : value.Reference}, null, 'pdalink fixedLeft')}} + {{/for}} + {{/if}} +
+ {{/for}} + {{/if}} + {{/if}} +{{/if}} \ No newline at end of file diff --git a/nano/templates/pda_mule.tmpl b/nano/templates/pda_mule.tmpl new file mode 100644 index 00000000000..cf3c5eff6f6 --- /dev/null +++ b/nano/templates/pda_mule.tmpl @@ -0,0 +1,118 @@ +{{if !data.mulebot.active}} + {{if data.mulebot.count == 0}} +

No bots found.

+ {{else}} +
+ Select a MULE: +
+
+ {{for data.mulebot.bots}} +
+ {{:helper.link(value.Name, 'gear', {'radiomenu' : "1", 'op' : "control",'bot' : value.ref}, null, 'pdalink fixedLeftWidest')}} (Location: {{:value.Location}}) +
+ {{/for}} + {{/if}} +
+ {{:helper.link('Scan for Bots','rss', {'radiomenu' : "1", 'op' : "scanbots"}, null, 'pdalink fixedLeftWidest')}} +{{else}} +

{{:data.mulebot.active}}

+ {{if data.mulebot.botstatus.mode == -1}} +

Waiting for response...

+ {{else}} +

Status:

+
+
+ Location: +
+
+ {{:data.mulebot.botstatus.loca}} +
+
+
+
+ Mode: +
+
+ + {{if data.mulebot.botstatus.mode == 0}} + Ready + {{else data.mulebot.botstatus.mode == 1}} + Loading/Unloading + {{else data.mulebot.botstatus.mode == 2}} + Navigating to Delivery Location + {{else data.mulebot.botstatus.mode == 3}} + Navigating to Home + {{else data.mulebot.botstatus.mode == 4}} + Waiting for Clear Path + {{else data.mulebot.botstatus.mode == 5 || data.mulebot.botstatus.mode == 6}} + Calculating navigation Path + {{else data.mulebot.botstatus.mode == 7}} + Unable to locate destination + {{/if}} + +
+
+
+
+ Current Load: +
+
+ + {{:helper.link(data.mulebot.botstatus.load == null ? 'None (Unload)' : data.mulebot.botstatus.load + ' (Unload)', 'archive', {'radiomenu' : "1", 'op' : "unload"},data.mulebot.botstatus.load == null ? 'disabled' : null, 'pdalink fixedLeftWidest')}} + +
+
+
+
+ Power: +
+
+ + {{:data.mulebot.botstatus.powr}}% + +
+
+
+
+ Destination: +
+
+ {{:helper.link(data.mulebot.botstatus.dest == null || data.mulebot.botstatus.dest == "" ? 'None (Set)' : data.mulebot.botstatus.dest + ' (Set)', 'gear', {'radiomenu' : "1", 'op' : "setdest"}, null, 'pdalink fixedLeftWidest')}} +
+
+
+
+ Home: +
+
+ {{if data.mulebot.botstatus.home == null}} None {{else}} {{:data.mulebot.botstatus.home}} {{/if}} +
+
+
+
+ Auto Return: +
+
+ {{:helper.link(data.mulebot.botstatus.retn == 1 ? 'ON' : 'OFF', 'gear', {'radiomenu' : "1", 'op' : (data.mulebot.botstatus.retn==1 ? "retoff" : "reton")}, null, 'pdalink fixedLeftWidest')}} +
+
+
+
+ Auto Pickup: +
+
+ {{:helper.link(data.mulebot.botstatus.pick==1? 'ON' : 'OFF', 'gear', {'radiomenu' : "1", 'op' : (data.mulebot.botstatus.pick==1 ? "pickoff" : "pickon")}, null, 'pdalink fixedLeftWidest')}} +
+
+
+
+ Functions: +
+
+ {{:helper.link('Stop', 'gear', {'radiomenu' : "1", 'op' : "stop"}, null, 'pdalink fixedLeft')}} + {{:helper.link('Proceed', 'gear', {'radiomenu' : "1", 'op' : "go"}, null, 'pdalink fixedLeft')}} + {{:helper.link('Return Home', 'gear', {'radiomenu' : "1", 'op' : "home"}, null, 'pdalink fixedLeft')}} +
+
+ {{/if}} +{{/if}} \ No newline at end of file diff --git a/nano/templates/pda_notekeeper.tmpl b/nano/templates/pda_notekeeper.tmpl new file mode 100644 index 00000000000..53db3be6438 --- /dev/null +++ b/nano/templates/pda_notekeeper.tmpl @@ -0,0 +1,21 @@ + +
+
+ Notes: +
+
+
+
+
+ {{:data.note}} +
+
+
+
+
+ {{:helper.link('Edit Notes', 'pencil-square-o', {'choice': "Edit"}, null, 'pdalink')}} +
+
\ No newline at end of file diff --git a/nano/templates/pda_power.tmpl b/nano/templates/pda_power.tmpl new file mode 100644 index 00000000000..7ba04188b71 --- /dev/null +++ b/nano/templates/pda_power.tmpl @@ -0,0 +1,49 @@ +{{if !data.records.powerconnected}} +
+
Select a power monitor:
+
+ {{for data.records.powermonitors}} +
+ {{:helper.link(value.Name, 'exclamation-circle', {'choice' : "Power Select", 'target' : value.ref}, null, 'pdalink fixedLeftWidest')}} +
+ {{/for}} +{{else}} +
+
+ Total Power: +
+
+ {{:data.records.poweravail}} W +
+
+
+
+ Total Load: +
+
+ {{:data.records.powerload}} W +
+
+
+
+ Total Demand: +
+
+ {{:data.records.powerdemand}} W +
+
+
+ + + {{for data.records.apcs}} + + {{:helper.string('', value.Equipment == "On" || value.Equipment == "AOn" ? '#4f7529' : '#8f1414', value.Equipment)}} + {{:helper.string('', value.Lights == "On" || value.Lights == "AOn" ? '#4f7529' : '#8f1414', value.Lights)}} + {{:helper.string('', value.Environment == "On" || value.Environment == "AOn" ? '#4f7529' : '#8f1414', value.Environment)}} + {{:helper.string('', value.CellStatus == "F" ? '#4f7529' : value.CellStatus == "C" ? '#cd6500' : '#8f1414', value.CellStatus == "M" ? 'No Cell' : value.CellPct + '%', value.CellStatus == "M" ? '' : ' (' + value.CellStatus + ')')}} + + + {{/for}} +
AreaEquip.LightingEnviron.CellLoad
{{:value.Name}}{1}{1}{1}{1}{2}{{:value.Load}}W
+
+{{/if}} \ No newline at end of file diff --git a/nano/templates/pda_secbot.tmpl b/nano/templates/pda_secbot.tmpl new file mode 100644 index 00000000000..6ff8c98e147 --- /dev/null +++ b/nano/templates/pda_secbot.tmpl @@ -0,0 +1,59 @@ +{{if !data.beepsky.active}} + {{if data.beepsky.count == 0}} +

No bots found.

+ {{else}} +
+ Select a bot: +
+
+ {{for data.beepsky.bots}} +
+ {{:helper.link(value.Name, 'gear', {'radiomenu' : "1", 'op' : "control",'bot' : value.ref}, null, 'pdalink fixedLeftWidest')}} (Location: {{:value.Location}}) +
+ {{/for}} + {{/if}} +
+ {{:helper.link('Scan for Bots','rss', {'radiomenu' : "1", 'op' : "scanbots"}, null, 'pdalink fixedLeftWidest')}} +{{else}} +

{{:data.beepsky.active}}

+ {{if data.beepsky.botstatus.mode == -1}} +

Waiting for response...

+ {{else}} +

Status:

+
+
+ Location: +
+
+ {{:data.beepsky.botstatus.loca}} +
+
+
+
+ Mode: +
+
+ + {{if data.beepsky.botstatus.mode ==0}} + Ready + {{else data.beepsky.botstatus.mode == 1}} + Apprehending target + {{else data.beepsky.botstatus.mode ==2 || data.beepsky.botstatus.mode == 3}} + Arresting target + {{else data.beepsky.botstatus.mode ==4}} + Starting patrol + {{else data.beepsky.botstatus.mode ==5}} + On Patrol + {{else data.beepsky.botstatus.mode ==6}} + Responding to summons + {{/if}} + +
+
+
+ {{:helper.link('Stop Patrol', 'gear', {'radiomenu' : "1", 'op' : "stop"}, null, 'pdalink fixedLeftWide')}} + {{:helper.link('Start Patrol', 'gear', {'radiomenu' : "1", 'op' : "go"}, null, 'pdalink fixedLeftWide')}} + {{:helper.link('Summon Bot', 'gear', {'radiomenu' : "1", 'op' : "summon"}, null, 'pdalink fixedLeftWide')}} +
+ {{/if}} +{{/if}} \ No newline at end of file diff --git a/nano/templates/pda_security.tmpl b/nano/templates/pda_security.tmpl new file mode 100644 index 00000000000..53d40185e05 --- /dev/null +++ b/nano/templates/pda_security.tmpl @@ -0,0 +1,50 @@ +{{if !data.records}} +
+
Select a record:
+
+ {{for data.recordsList}} +
+ {{:helper.link(value.Name, 'user', {'choice' : "Records", 'target' : value.ref}, null, 'pdalink fixedLeftWidest')}} +
+ {{empty}} +
+ No records found. +
+ {{/for}} +{{else}} +
+
+
+ {{if data.records.general}} + Name: {{:data.records.general.name}}
+ Sex: {{:data.records.general.sex}}
+ Species: {{:data.records.general.species}}
+ Age: {{:data.records.general.age}}
+ Rank: {{:data.records.general.rank}}
+ Fingerprint: {{:data.records.general.fingerprint}}
+ Physical Status: {{:data.records.general.p_stat}}
+ Mental Status: {{:data.records.general.m_stat}}

+ {{else}} + + General Record Lost!

+
+ {{/if}} + {{if data.records.security}} +
+
Security Data:
+
+ Criminal Status: {{:data.records.security.criminal}}

+ Minor Crimes: {{:data.records.security.mi_crim}}
+ Details: {{:data.records.security.mi_crim_d}}

+ Major Crimes: {{:data.records.security.ma_crim}}
+ Details: {{:data.records.security.ma_crim_d}}

+ Important Notes: {{:data.records.security.notes}} + {{else}} + + Security Record Lost!

+
+ {{/if}} +
+
+
+{{/if}} \ No newline at end of file diff --git a/nano/templates/pda_signaller.tmpl b/nano/templates/pda_signaller.tmpl new file mode 100644 index 00000000000..2b5f148b025 --- /dev/null +++ b/nano/templates/pda_signaller.tmpl @@ -0,0 +1,38 @@ + +
+
+ Frequency: +
+
+ {{:data.signal_freq}} +
+   + {{:helper.link('-1', null, {'choice' : "Signal Frequency", 'sfreq' : "-10"}, null, null)}}  + {{:helper.link('-.2', null, {'choice' : "Signal Frequency", 'sfreq' : "-2"}, null, null)}}  + + {{:helper.link('+.2', null, {'choice' : "Signal Frequency", 'sfreq' : "2"}, null, null)}}  + {{:helper.link('+1', null, {'choice' : "Signal Frequency", 'sfreq' : "10"}, null, null)}} +
+
+
+
+
+
+ Code: +
+
+ + {{:data.signal_code}}
+
+ {{:helper.link('-5', null, {'choice' : "Signal Code", 'scode' : "-5"}, null, null)}} + {{:helper.link('-1', null, {'choice' : "Signal Code", 'scode' : "-1"}, null, null)}} + {{:helper.link('+1', null, {'choice' : "Signal Code", 'scode' : "1"}, null, null)}} + {{:helper.link('+5', null, {'choice' : "Signal Code", 'scode' : "5"}, null, null)}} +
+
+
+ {{:helper.link('Send Signal', 'exclamation-circle', {'choice' : "Send Signal"}, null, null)}} +
\ No newline at end of file diff --git a/nano/templates/pda_status_display.tmpl b/nano/templates/pda_status_display.tmpl new file mode 100644 index 00000000000..8b153ad0ffd --- /dev/null +++ b/nano/templates/pda_status_display.tmpl @@ -0,0 +1,44 @@ + +
+
+ Code: +
+
+ {{:helper.link('Clear', 'trash', {'choice' : "Status", 'statdisp' : "blank"}, null, 'pdalink fixedLeftWide')}} + {{:helper.link('Shuttle ETA', 'gear', {'cartmenu' : "1", 'choice' : "Status", 'statdisp' : "shuttle"}, null, 'pdalink fixedLeftWide')}} + {{:helper.link('Message', 'gear', {'choice' : "Status", 'statdisp' : "message"}, null, 'pdalink fixedLeftWide')}} +
+
+
+
+
+ Message line 1 +
+
+ {{:helper.link(data.records.message1 + ' (set)', 'pencil', {'choice' : "Status", 'statdisp' : "setmsg1"}, null, 'pdalink fixedLeftWide')}} +
+
+
+
+ Message line 2 +
+
+ {{:helper.link(data.records.message2 + ' (set)', 'pencil', {'choice' : "Status", 'statdisp' : "setmsg2"}, null, 'pdalink fixedLeftWide')}} +
+
+ +
+
+
+ ALERT!: +
+
+ {{:helper.link('None', 'bell', {'choice' : "Status", 'statdisp' : "alert", 'alert' : "default"}, null, 'pdalink fixedLeftWide')}} + {{:helper.link('Red Alert', 'bell', {'choice' : "Status", 'statdisp' : "alert", 'alert' : "redalert"}, null, 'pdalink fixedLeftWide')}} + {{:helper.link('Lockdown', 'exclamation-circle', {'choice' : "Status", 'statdisp' : "alert", 'alert' : "lockdown"}, null, 'pdalink fixedLeftWide')}} + {{:helper.link('Biohazard', 'exclamation-circle', {'choice' : "Status", 'statdisp' : "alert", 'alert' : "biohazard"}, null, 'pdalink fixedLeftWide')}} +
+
\ No newline at end of file diff --git a/nano/templates/pda_supply.tmpl b/nano/templates/pda_supply.tmpl new file mode 100644 index 00000000000..810fc193769 --- /dev/null +++ b/nano/templates/pda_supply.tmpl @@ -0,0 +1,39 @@ +
+
+ Location: +
+
+ + {{if data.supply.shuttle_moving}} + Moving to {{:data.supply.shuttle_loc}} + {{else}} + Shuttle at {{:data.supply.shuttle_loc}} + {{/if}} +
+ {{:data.supply.shuttle_time}} +
+
+
+
+
+
+ Current Approved Orders
+ {{if data.supply.approved_count == 0}} + No current approved orders

+ {{else}} + {{for data.supply.approved}} + #{{:value.Number}} - {{:value.Name}} approved by {{:value.OrderedBy}}
{{if value.Comment != ""}} {{:value.Comment}}
{{/if}}
+ {{/for}} + {{/if}} +

+ Current Requested Orders
+ {{if data.supply.requests_count == 0}} + No current requested orders

+ {{else}} + {{for data.supply.requests}} + #{{:value.Number}} - {{:value.Name}} requested by {{:value.OrderedBy}}
{{if value.Comment != ""}} {{:value.Comment}}
{{/if}}
+ {{/for}} + {{/if}} +
+
+
\ No newline at end of file diff --git a/paradise.dme b/paradise.dme index 0b932735ca4..7f480172d9a 100644 --- a/paradise.dme +++ b/paradise.dme @@ -31,6 +31,7 @@ #include "code\__DEFINES\math.dm" #include "code\__DEFINES\misc.dm" #include "code\__DEFINES\mob.dm" +#include "code\__DEFINES\pda.dm" #include "code\__DEFINES\preferences.dm" #include "code\__DEFINES\process_scheduler.dm" #include "code\__DEFINES\qdel.dm" @@ -672,10 +673,18 @@ #include "code\game\objects\items\devices\uplinks.dm" #include "code\game\objects\items\devices\violin.dm" #include "code\game\objects\items\devices\whistle.dm" +#include "code\game\objects\items\devices\PDA\ai.dm" +#include "code\game\objects\items\devices\PDA\app.dm" #include "code\game\objects\items\devices\PDA\cart.dm" +#include "code\game\objects\items\devices\PDA\cart_apps.dm" #include "code\game\objects\items\devices\PDA\chatroom.dm" +#include "code\game\objects\items\devices\PDA\core_apps.dm" +#include "code\game\objects\items\devices\PDA\messenger.dm" +#include "code\game\objects\items\devices\PDA\messenger_plugins.dm" #include "code\game\objects\items\devices\PDA\PDA.dm" +#include "code\game\objects\items\devices\PDA\pdas.dm" #include "code\game\objects\items\devices\PDA\radio.dm" +#include "code\game\objects\items\devices\PDA\utilities.dm" #include "code\game\objects\items\devices\radio\beacon.dm" #include "code\game\objects\items\devices\radio\electropack.dm" #include "code\game\objects\items\devices\radio\encryptionkey.dm"