diff --git a/code/_onclick/ai.dm b/code/_onclick/ai.dm index 859884a8b7..76b18f7222 100644 --- a/code/_onclick/ai.dm +++ b/code/_onclick/ai.dm @@ -141,8 +141,9 @@ return 1 /obj/machinery/turretid/AICtrlClick() //turns off/on Turrets - Topic(src, list("command"="enable", "value"="[!enabled]")) - return 1 + enabled = !enabled + updateTurrets() + return TRUE /atom/proc/AIAltClick(var/atom/A) return AltClick(A) @@ -156,8 +157,10 @@ return 1 /obj/machinery/turretid/AIAltClick() //toggles lethal on turrets - Topic(src, list("command"="lethal", "value"="[!lethal]")) - return 1 + if(lethal_is_configurable) + lethal = !lethal + updateTurrets() + return TRUE /atom/proc/AIMiddleClick(var/mob/living/silicon/user) return 0 diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index 66cf3d1c12..5e5f044ac2 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -515,7 +515,7 @@ if("Show Crew Manifest") if(isAI(usr)) var/mob/living/silicon/ai/AI = usr - AI.ai_roster() + AI.subsystem_crew_manifest() if("Show Alerts") if(isAI(usr)) @@ -540,12 +540,14 @@ if("PDA - Send Message") if(isAI(usr)) var/mob/living/silicon/ai/AI = usr - AI.aiPDA.cmd_send_pdamesg(usr) + AI.aiPDA.start_program(AI.aiPDA.find_program(/datum/data/pda/app/messenger)) + AI.aiPDA.cmd_pda_open_ui(usr) if("PDA - Show Message Log") if(isAI(usr)) var/mob/living/silicon/ai/AI = usr - AI.aiPDA.cmd_show_message_log(usr) + AI.aiPDA.start_program(AI.aiPDA.find_program(/datum/data/pda/app/messenger)) + AI.aiPDA.cmd_pda_open_ui(usr) if("Take Image") if(isAI(usr)) diff --git a/code/controllers/subsystems/nanoui.dm b/code/controllers/subsystems/nanoui.dm deleted file mode 100644 index c916eb2739..0000000000 --- a/code/controllers/subsystems/nanoui.dm +++ /dev/null @@ -1,22 +0,0 @@ -SUBSYSTEM_DEF(nanoui) - name = "NanoUI" - wait = 5 - flags = SS_NO_INIT - // a list of current open /nanoui UIs, grouped by src_object and ui_key - var/list/open_uis = list() - // a list of current open /nanoui UIs, not grouped, for use in processing - var/list/processing_uis = list() - -/datum/controller/subsystem/nanoui/Recover() - if(SSnanoui.open_uis) - open_uis |= SSnanoui.open_uis - if(SSnanoui.processing_uis) - processing_uis |= SSnanoui.processing_uis - -/datum/controller/subsystem/nanoui/stat_entry() - return ..("[processing_uis.len] UIs") - -/datum/controller/subsystem/nanoui/fire(resumed) - for(var/thing in processing_uis) - var/datum/nanoui/UI = thing - UI.process() diff --git a/code/controllers/subsystems/persistence.dm b/code/controllers/subsystems/persistence.dm index c2724c2d60..00c08363de 100644 --- a/code/controllers/subsystems/persistence.dm +++ b/code/controllers/subsystems/persistence.dm @@ -31,7 +31,7 @@ SUBSYSTEM_DEF(persistence) return // if((!T.z in GLOB.using_map.station_levels) || !initialized) - if(!T.z in using_map.station_levels) + if(!(T.z in using_map.station_levels)) return if(!tracking_values[track_type]) diff --git a/code/datums/datum.dm b/code/datums/datum.dm index 61eb4c6953..d806728f5d 100644 --- a/code/datums/datum.dm +++ b/code/datums/datum.dm @@ -31,5 +31,5 @@ weakref = null // Clear this reference to ensure it's kept for as brief duration as possible. tag = null - SSnanoui.close_uis(src) + SStgui.close_uis(src) return QDEL_HINT_QUEUE diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 10a7b4b7b9..bca9df5ae1 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -85,7 +85,6 @@ current.verbs -= /datum/changeling/proc/EvolutionMenu current.mind = null - SSnanoui.user_transferred(current, new_character) // transfer active NanoUI instances to new user if(new_character.mind) //remove any mind currently in our new body's mind variable new_character.mind.current = null diff --git a/code/datums/uplink/uplink_items.dm b/code/datums/uplink/uplink_items.dm index cca1933c9c..8d9de8f732 100644 --- a/code/datums/uplink/uplink_items.dm +++ b/code/datums/uplink/uplink_items.dm @@ -51,7 +51,7 @@ var/datum/uplink/uplink = new() if(!can_buy(U)) return - if(U.CanUseTopic(user, inventory_state) != STATUS_INTERACTIVE) + if(U.CanUseTopic(user, GLOB.tgui_inventory_state) != STATUS_INTERACTIVE) return var/cost = cost(U.uses, U) diff --git a/code/game/gamemodes/changeling/powers/fabricate_clothing.dm b/code/game/gamemodes/changeling/powers/fabricate_clothing.dm index b90b402e78..6ec87a64d4 100644 --- a/code/game/gamemodes/changeling/powers/fabricate_clothing.dm +++ b/code/game/gamemodes/changeling/powers/fabricate_clothing.dm @@ -286,5 +286,5 @@ var/global/list/changeling_fabricated_clothing = list( if(!registered_user) registered_user = usr usr.set_id_info(src) - ui_interact(registered_user) + tgui_interact(registered_user) ..() \ No newline at end of file diff --git a/code/game/machinery/atmoalter/canister.dm b/code/game/machinery/atmoalter/canister.dm index 6fe30aeaab..2d5e39b1b7 100644 --- a/code/game/machinery/atmoalter/canister.dm +++ b/code/game/machinery/atmoalter/canister.dm @@ -260,7 +260,7 @@ update_flag ..() - SSnanoui.update_uis(src) // Update all NanoUIs attached to src + SStgui.update_uis(src) // Update all NanoUIs attached to src /obj/machinery/portable_atmospherics/canister/attack_ai(var/mob/user as mob) return src.attack_hand(user) diff --git a/code/game/machinery/computer/arcade.dm b/code/game/machinery/computer/arcade.dm index 8ef01c9b64..6921cf989c 100644 --- a/code/game/machinery/computer/arcade.dm +++ b/code/game/machinery/computer/arcade.dm @@ -92,8 +92,11 @@ var/blocked = 0 //Player cannot attack/heal while set var/turtle = 0 -/obj/machinery/computer/arcade/battle/New() - ..() +/obj/machinery/computer/arcade/battle/Initialize() + . = ..() + randomize_characters() + +/obj/machinery/computer/arcade/battle/proc/randomize_characters() var/name_action var/name_part1 var/name_part2 @@ -111,17 +114,17 @@ if(..()) return user.set_machine(src) - ui_interact(user) + tgui_interact(user) -/** - * Display the NanoUI window for the arcade machine. - * - * See NanoUI documentation for details. - */ -/obj/machinery/computer/arcade/battle/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - user.set_machine(src) +/obj/machinery/computer/arcade/battle/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "ArcadeBattle", name) + ui.open() - var/list/data = list() +/obj/machinery/computer/arcade/battle/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state) + var/list/data = ..() + data["name"] = name data["temp"] = temp data["enemyAction"] = enemy_action data["enemyName"] = enemy_name @@ -129,59 +132,54 @@ data["playerMP"] = player_mp data["enemyHP"] = enemy_hp data["gameOver"] = gameover + return data - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - ui = new(user, src, ui_key, "arcade_battle.tmpl", src.name, 400, 300) - ui.set_initial_data(data) - ui.open() - //ui.set_auto_update(2) - -/obj/machinery/computer/arcade/battle/Topic(href, href_list) +/obj/machinery/computer/arcade/battle/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) if(..()) - return 1 + return TRUE - if (!blocked && !gameover) - if (href_list["attack"]) - blocked = 1 - var/attackamt = rand(2,6) - temp = "You attack for [attackamt] damage!" - playsound(src, 'sound/arcade/hit.ogg', 50, 1, extrarange = -3, falloff = 0.1, ignore_walls = FALSE) - if(turtle > 0) - turtle-- + if(!blocked && !gameover) + switch(action) + if("attack") + blocked = 1 + var/attackamt = rand(2,6) + temp = "You attack for [attackamt] damage!" + playsound(src, 'sound/arcade/hit.ogg', 50, 1, extrarange = -3, falloff = 0.1, ignore_walls = FALSE) + if(turtle > 0) + turtle-- - sleep(10) - enemy_hp -= attackamt - arcade_action() + sleep(10) + enemy_hp -= attackamt + arcade_action() - else if (href_list["heal"]) - blocked = 1 - var/pointamt = rand(1,3) - var/healamt = rand(6,8) - temp = "You use [pointamt] magic to heal for [healamt] damage!" - playsound(src, 'sound/arcade/heal.ogg', 50, 1, extrarange = -3, falloff = 0.1, ignore_walls = FALSE) - turtle++ + if("heal") + blocked = 1 + var/pointamt = rand(1,3) + var/healamt = rand(6,8) + temp = "You use [pointamt] magic to heal for [healamt] damage!" + playsound(src, 'sound/arcade/heal.ogg', 50, 1, extrarange = -3, falloff = 0.1, ignore_walls = FALSE) + turtle++ - sleep(10) - player_mp -= pointamt - player_hp += healamt - blocked = 1 - arcade_action() + sleep(10) + player_mp -= pointamt + player_hp += healamt + blocked = 1 + arcade_action() - else if (href_list["charge"]) - blocked = 1 - var/chargeamt = rand(4,7) - temp = "You regain [chargeamt] points" - playsound(src, 'sound/arcade/mana.ogg', 50, 1, extrarange = -3, falloff = 0.1, ignore_walls = FALSE) - player_mp += chargeamt - if(turtle > 0) - turtle-- + if("charge") + blocked = 1 + var/chargeamt = rand(4,7) + temp = "You regain [chargeamt] points" + playsound(src, 'sound/arcade/mana.ogg', 50, 1, extrarange = -3, falloff = 0.1, ignore_walls = FALSE) + player_mp += chargeamt + if(turtle > 0) + turtle-- - sleep(10) - arcade_action() + sleep(10) + arcade_action() - else if (href_list["newgame"]) //Reset everything + if(action == "newgame") //Reset everything temp = "New Round" player_hp = 30 player_mp = 10 @@ -191,12 +189,11 @@ turtle = 0 if(emagged) - src.New() + randomize_characters() emagged = 0 - src.add_fingerprint(usr) - SSnanoui.update_uis(src) - return + add_fingerprint(usr) + return TRUE /obj/machinery/computer/arcade/battle/proc/arcade_action() if ((enemy_mp <= 0) || (enemy_hp <= 0)) @@ -211,7 +208,7 @@ new /obj/item/clothing/head/collectable/petehat(src.loc) message_admins("[key_name_admin(usr)] has outbombed Cuban Pete and been awarded a bomb.") log_game("[key_name_admin(usr)] has outbombed Cuban Pete and been awarded a bomb.") - src.New() + randomize_characters() emagged = 0 else if(!contents.len) feedback_inc("arcade_win_normal") diff --git a/code/game/machinery/computer/guestpass.dm b/code/game/machinery/computer/guestpass.dm index eb634c249f..1a4ec083df 100644 --- a/code/game/machinery/computer/guestpass.dm +++ b/code/game/machinery/computer/guestpass.dm @@ -13,14 +13,14 @@ var/reason = "NOT SPECIFIED" /obj/item/weapon/card/id/guest/GetAccess() - if (world.time > expiration_time) + if(world.time > expiration_time) return access else return temp_access /obj/item/weapon/card/id/guest/examine(mob/user) . = ..() - if (world.time < expiration_time) + if(world.time < expiration_time) . += "This pass expires at [worldtime2stationtime(expiration_time)]." else . += "It expired at [worldtime2stationtime(expiration_time)]." @@ -28,7 +28,7 @@ /obj/item/weapon/card/id/guest/read() if(!Adjacent(usr)) return //Too far to read - if (world.time > expiration_time) + if(world.time > expiration_time) to_chat(usr, "This pass expired at [worldtime2stationtime(expiration_time)].") else to_chat(usr, "This pass expires at [worldtime2stationtime(expiration_time)].") @@ -105,7 +105,7 @@ if(!giver && user.unEquip(I)) I.forceMove(src) giver = I - SSnanoui.update_uis(src) + SStgui.update_uis(src) else if(giver) to_chat(user, "There is already ID card inside.") return @@ -119,128 +119,119 @@ return user.set_machine(src) + tgui_interact(user) - ui_interact(user) +/obj/machinery/computer/guestpass/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "GuestPass", name) + ui.open() -/** - * Display the NanoUI window for the guest pass console. - * - * See NanoUI documentation for details. - */ -/obj/machinery/computer/guestpass/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - user.set_machine(src) +/obj/machinery/computer/guestpass/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state) + var/list/data = ..() - var/list/data = list() + var/list/area_list = list() - var/area_list[0] - - if (giver && giver.access) + data["access"] = null + if(giver && giver.access) data["access"] = giver.access for (var/A in giver.access) if(A in accesses) - area_list[++area_list.len] = list("area" = A, "area_name" = get_access_desc(A), "on" = 1) + area_list.Add(list(list("area" = A, "area_name" = get_access_desc(A), "on" = 1))) else - area_list[++area_list.len] = list("area" = A, "area_name" = get_access_desc(A), "on" = null) + area_list.Add(list(list("area" = A, "area_name" = get_access_desc(A), "on" = null))) + data["area"] = area_list data["giver"] = giver data["giveName"] = giv_name data["reason"] = reason data["duration"] = duration - data["area"] = area_list data["mode"] = mode data["log"] = internal_log data["uid"] = uid - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - ui = new(user, src, ui_key, "guest_pass.tmpl", src.name, 400, 520) - ui.set_initial_data(data) - ui.open() - //ui.set_auto_update(5) + return data -/obj/machinery/computer/guestpass/Topic(href, href_list) +/obj/machinery/computer/guestpass/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) if(..()) - return 1 - usr.set_machine(src) - if (href_list["mode"]) - mode = href_list["mode"] + return TRUE - if (href_list["choice"]) - switch(href_list["choice"]) - if ("giv_name") - var/nam = sanitizeName(input("Person pass is issued to", "Name", giv_name) as text|null) - if (nam) - giv_name = nam - if ("reason") - var/reas = sanitize(input("Reason why pass is issued", "Reason", reason) as text|null) - if(reas) - reason = reas - if ("duration") - var/dur = input("Duration (in minutes) during which pass is valid (up to 120 minutes).", "Duration") as num|null - if (dur) - if (dur > 0 && dur <= 120) - duration = dur - else - to_chat(usr, "Invalid duration.") - if ("access") - var/A = text2num(href_list["access"]) - if (A in accesses) - accesses.Remove(A) + switch(action) + if("mode") + mode = params["mode"] + + if("giv_name") + var/nam = sanitizeName(input("Person pass is issued to", "Name", giv_name) as text|null) + if(nam) + giv_name = nam + if("reason") + var/reas = sanitize(input("Reason why pass is issued", "Reason", reason) as text|null) + if(reas) + reason = reas + if("duration") + var/dur = input("Duration (in minutes) during which pass is valid (up to 120 minutes).", "Duration") as num|null + if(dur) + if(dur > 0 && dur <= 120) + duration = dur else - if(A in giver.access) //Let's make sure the ID card actually has the access. - accesses.Add(A) - else - to_chat(usr, "Invalid selection, please consult technical support if there are any issues.") - log_debug("[key_name_admin(usr)] tried selecting an invalid guest pass terminal option.") - if (href_list["action"]) - switch(href_list["action"]) - if ("id") - if (giver) - if(ishuman(usr)) - giver.loc = usr.loc - if(!usr.get_active_hand()) - usr.put_in_hands(giver) - giver = null - else - giver.loc = src.loc - giver = null - accesses.Cut() + to_chat(usr, "Invalid duration.") + if("access") + var/A = text2num(params["access"]) + if(A in accesses) + accesses.Remove(A) + else + if(A in giver.access) //Let's make sure the ID card actually has the access. + accesses.Add(A) else - var/obj/item/I = usr.get_active_hand() - if (istype(I, /obj/item/weapon/card/id) && usr.unEquip(I)) - I.loc = src - giver = I - - if ("print") - var/dat = "

Activity log of guest pass terminal #[uid]


" - for (var/entry in internal_log) - dat += "[entry]

" - //to_chat(usr, "Printing the log, standby...") - //sleep(50) - var/obj/item/weapon/paper/P = new/obj/item/weapon/paper( loc ) - P.name = "activity log" - P.info = dat - - if ("issue") - if (giver) - var/number = add_zero("[rand(0,9999)]", 4) - var/entry = "\[[stationtime2text()]\] Pass #[number] issued by [giver.registered_name] ([giver.assignment]) to [giv_name]. Reason: [reason]. Grants access to following areas: " - for (var/i=1 to accesses.len) - var/A = accesses[i] - if (A) - var/area = get_access_desc(A) - entry += "[i > 1 ? ", [area]" : "[area]"]" - entry += ". Expires at [worldtime2stationtime(world.time + duration*10*60)]." - internal_log.Add(entry) - - var/obj/item/weapon/card/id/guest/pass = new(src.loc) - pass.temp_access = accesses.Copy() - pass.registered_name = giv_name - pass.expiration_time = world.time + duration*10*60 - pass.reason = reason - pass.name = "guest pass #[number]" + to_chat(usr, "Invalid selection, please consult technical support if there are any issues.") + log_debug("[key_name_admin(usr)] tried selecting an invalid guest pass terminal option.") + if("id") + if(giver) + if(ishuman(usr)) + giver.loc = usr.loc + if(!usr.get_active_hand()) + usr.put_in_hands(giver) + giver = null else - to_chat(usr, "Cannot issue pass without issuing ID.") + giver.loc = src.loc + giver = null + accesses.Cut() + else + var/obj/item/I = usr.get_active_hand() + if(istype(I, /obj/item/weapon/card/id) && usr.unEquip(I)) + I.loc = src + giver = I - src.add_fingerprint(usr) - SSnanoui.update_uis(src) \ No newline at end of file + if("print") + var/dat = "

Activity log of guest pass terminal #[uid]


" + for (var/entry in internal_log) + dat += "[entry]

" + //to_chat(usr, "Printing the log, standby...") + //sleep(50) + var/obj/item/weapon/paper/P = new/obj/item/weapon/paper( loc ) + P.name = "activity log" + P.info = dat + + if("issue") + if(giver) + var/number = add_zero("[rand(0,9999)]", 4) + var/entry = "\[[stationtime2text()]\] Pass #[number] issued by [giver.registered_name] ([giver.assignment]) to [giv_name]. Reason: [reason]. Grants access to following areas: " + for (var/i=1 to accesses.len) + var/A = accesses[i] + if(A) + var/area = get_access_desc(A) + entry += "[i > 1 ? ", [area]" : "[area]"]" + entry += ". Expires at [worldtime2stationtime(world.time + duration*10*60)]." + internal_log.Add(entry) + + var/obj/item/weapon/card/id/guest/pass = new(src.loc) + pass.temp_access = accesses.Copy() + pass.registered_name = giv_name + pass.expiration_time = world.time + duration*10*60 + pass.reason = reason + pass.name = "guest pass #[number]" + else + to_chat(usr, "Cannot issue pass without issuing ID.") + + add_fingerprint(usr) + return TRUE \ No newline at end of file diff --git a/code/game/machinery/computer/timeclock_vr.dm b/code/game/machinery/computer/timeclock_vr.dm index a94b338320..8cfc711c18 100644 --- a/code/game/machinery/computer/timeclock_vr.dm +++ b/code/game/machinery/computer/timeclock_vr.dm @@ -55,7 +55,7 @@ if(!card && user.unEquip(I)) I.forceMove(src) card = I - SSnanoui.update_uis(src) + SStgui.update_uis(src) update_icon() else if(card) to_chat(user, "There is already ID card inside.") diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 7eb9e4a342..014efcb581 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -851,11 +851,13 @@ About the new airlock wires panel: /obj/machinery/door/airlock/attack_ghost(mob/user) tgui_interact(user) -/obj/machinery/door/airlock/tgui_interact(mob/user, datum/tgui/ui) +/obj/machinery/door/airlock/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui, datum/tgui_state/custom_state) ui = SStgui.try_update_ui(user, src, ui) if(!ui) ui = new(user, src, "AiAirlock", name) ui.open() + if(custom_state) + ui.set_state(custom_state) return TRUE /obj/machinery/door/airlock/tgui_data(mob/user) diff --git a/code/game/machinery/embedded_controller/airlock_controllers_dummy.dm b/code/game/machinery/embedded_controller/airlock_controllers_dummy.dm index ef6367758f..9e65c06bcd 100644 --- a/code/game/machinery/embedded_controller/airlock_controllers_dummy.dm +++ b/code/game/machinery/embedded_controller/airlock_controllers_dummy.dm @@ -7,7 +7,6 @@ layer = ABOVE_OBJ_LAYER var/id_tag - var/datum/topic_state/remote/remote_state var/obj/machinery/embedded_controller/radio/airlock/master_controller /obj/machinery/dummy_airlock_controller/process() @@ -25,15 +24,10 @@ break if(!master_controller) qdel(src) - else - remote_state = new /datum/topic_state/remote(src, master_controller) /obj/machinery/dummy_airlock_controller/Destroy() if(master_controller) master_controller.dummy_terminals -= src - if(remote_state) - qdel(remote_state) - remote_state = null return ..() /obj/machinery/dummy_airlock_controller/interface_interact(var/mob/user) diff --git a/code/game/machinery/jukebox.dm b/code/game/machinery/jukebox.dm index 00a8e68760..e8e741b578 100644 --- a/code/game/machinery/jukebox.dm +++ b/code/game/machinery/jukebox.dm @@ -192,7 +192,6 @@ if(inoperable()) to_chat(usr, "\The [src] doesn't appear to function.") return - ui_interact(user) tgui_interact(user) /obj/machinery/media/jukebox/tgui_status(mob/user) diff --git a/code/game/machinery/oxygen_pump.dm b/code/game/machinery/oxygen_pump.dm index 37c75957be..f7821a4e84 100644 --- a/code/game/machinery/oxygen_pump.dm +++ b/code/game/machinery/oxygen_pump.dm @@ -79,7 +79,7 @@ update_use_power(USE_POWER_IDLE) /obj/machinery/oxygen_pump/attack_ai(mob/user as mob) - ui_interact(user) + tgui_interact(user) /obj/machinery/oxygen_pump/proc/attach_mask(var/mob/living/carbon/C) if(C && istype(C)) @@ -176,61 +176,60 @@ set src in oview(1) set category = "Object" set name = "Show Tank Settings" - ui_interact(usr) + tgui_interact(usr) -//GUI Tank Setup -/obj/machinery/oxygen_pump/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - var/data[0] +/obj/machinery/oxygen_pump/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui) if(!tank) - to_chat(usr, "It is missing a tank!") - data["tankPressure"] = 0 - data["releasePressure"] = 0 - data["defaultReleasePressure"] = 0 - data["maxReleasePressure"] = 0 - data["maskConnected"] = 0 - data["tankInstalled"] = 0 - // this is the data which will be sent to the ui + to_chat(user, "[src] is missing a tank.") + if(ui) + ui.close() + return + + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "Tank", name) + ui.open() + +/obj/machinery/oxygen_pump/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state) + var/list/data = ..() + + data["showToggle"] = FALSE + data["maskConnected"] = !!breather + + data["tankPressure"] = 0 + data["releasePressure"] = 0 + data["defaultReleasePressure"] = 0 + data["minReleasePressure"] = 0 + data["releasePressure"] = round(tank.distribute_pressure ? tank.distribute_pressure : 0) + data["maxReleasePressure"] = round(TANK_MAX_RELEASE_PRESSURE) + if(tank) data["tankPressure"] = round(tank.air_contents.return_pressure() ? tank.air_contents.return_pressure() : 0) - data["releasePressure"] = round(tank.distribute_pressure ? tank.distribute_pressure : 0) data["defaultReleasePressure"] = round(TANK_DEFAULT_RELEASE_PRESSURE) - data["maxReleasePressure"] = round(TANK_MAX_RELEASE_PRESSURE) - data["maskConnected"] = 0 - data["tankInstalled"] = 1 - if(!breather) - data["maskConnected"] = 0 - if(breather) - data["maskConnected"] = 1 + return data - - // update the ui if it exists, returns null if no ui is passed/found - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - // 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, "Oxygen_pump.tmpl", "Tank", 500, 300) - // 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(1) - -/obj/machinery/oxygen_pump/Topic(href, href_list) +/obj/machinery/oxygen_pump/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) if(..()) - return 1 + return TRUE - if (href_list["dist_p"]) - if (href_list["dist_p"] == "reset") - tank.distribute_pressure = TANK_DEFAULT_RELEASE_PRESSURE - else if (href_list["dist_p"] == "max") - tank.distribute_pressure = TANK_MAX_RELEASE_PRESSURE - else - var/cp = text2num(href_list["dist_p"]) - tank.distribute_pressure += cp - tank.distribute_pressure = min(max(round(tank.distribute_pressure), 0), TANK_MAX_RELEASE_PRESSURE) - return 1 + switch(action) + if("pressure") + var/pressure = params["pressure"] + if(pressure == "reset") + pressure = TANK_DEFAULT_RELEASE_PRESSURE + . = TRUE + else if(pressure == "min") + pressure = 0 + . = TRUE + else if(pressure == "max") + pressure = TANK_MAX_RELEASE_PRESSURE + . = TRUE + else if(text2num(pressure) != null) + pressure = text2num(pressure) + . = TRUE + if(.) + tank.distribute_pressure = clamp(round(pressure), 0, TANK_MAX_RELEASE_PRESSURE) /obj/machinery/oxygen_pump/anesthetic name = "anesthetic pump" diff --git a/code/game/machinery/partslathe_vr.dm b/code/game/machinery/partslathe_vr.dm index aab15f40f9..c5ddcff900 100644 --- a/code/game/machinery/partslathe_vr.dm +++ b/code/game/machinery/partslathe_vr.dm @@ -233,7 +233,6 @@ /obj/machinery/partslathe/attack_hand(mob/user) if(..()) return - ui_interact(user) tgui_interact(user) /obj/machinery/partslathe/ui_assets(mob/user) diff --git a/code/game/machinery/pointdefense.dm b/code/game/machinery/pointdefense.dm index 8eeb73fbc5..5b10e398a3 100644 --- a/code/game/machinery/pointdefense.dm +++ b/code/game/machinery/pointdefense.dm @@ -95,7 +95,7 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/power/pointdefense) /obj/machinery/pointdefense_control/attackby(var/obj/item/W, var/mob/user) if(W?.is_multitool()) var/new_ident = input(user, "Enter a new ident tag.", "[src]", id_tag) as null|text - if(new_ident && new_ident != id_tag && user.Adjacent(src) && CanInteract(user, physical_state)) + if(new_ident && new_ident != id_tag && user.Adjacent(src) && CanInteract(user, GLOB.tgui_physical_state)) // Check for duplicate controllers with this ID for(var/thing in pointdefense_controllers) var/obj/machinery/pointdefense_control/PC = thing @@ -211,7 +211,7 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/power/pointdefense) /obj/machinery/power/pointdefense/attackby(var/obj/item/W, var/mob/user) if(W?.is_multitool()) var/new_ident = input(user, "Enter a new ident tag.", "[src]", id_tag) as null|text - if(new_ident && new_ident != id_tag && user.Adjacent(src) && CanInteract(user, physical_state)) + if(new_ident && new_ident != id_tag && user.Adjacent(src) && CanInteract(user, GLOB.tgui_physical_state)) to_chat(user, "You register [src] with the [new_ident] network.") id_tag = new_ident return diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm index 1ed44c61bc..01a890bd79 100644 --- a/code/game/machinery/portable_turret.dm +++ b/code/game/machinery/portable_turret.dm @@ -66,6 +66,7 @@ var/last_fired = FALSE //TRUE: if the turret is cooling down from a shot, FALSE: turret is ready to fire var/shot_delay = 1.5 SECONDS //1.5 seconds between each shot + var/targetting_is_configurable = TRUE // if false, you cannot change who this turret attacks via its UI var/check_arrest = TRUE //checks if the perp is set to arrest var/check_records = TRUE //checks if a security record exists at all var/check_weapons = FALSE //checks if it can shoot people that have a weapon they aren't authorized to have @@ -81,6 +82,7 @@ var/enabled = TRUE //determines if the turret is on var/lethal = FALSE //whether in lethal or stun mode + var/lethal_is_configurable = TRUE // if false, its lethal setting cannot be changed var/disabled = FALSE var/shot_sound //what sound should play when the turret fires @@ -214,6 +216,9 @@ req_one_access = list() installation = /obj/item/weapon/gun/energy/lasertag/omni + targetting_is_configurable = FALSE + lethal_is_configurable = FALSE + locked = FALSE enabled = FALSE anchored = FALSE @@ -262,43 +267,14 @@ if(istype(M.wear_suit, /obj/item/clothing/suit/bluetag) && check_weapons) // Checks if they are a blue player return TURRET_PRIORITY_TARGET -/obj/machinery/porta_turret/lasertag/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - var/data[0] - data["access"] = !isLocked(user) - data["locked"] = locked - data["enabled"] = enabled - //data["is_lethal"] = 1 // VOREStation Removal of "Lethal" setting - it does nothing. Rykka did dis. - //data["lethal"] = lethal // VOREStation Removal of "Lethal" setting - it does nothing. Rykka did dis. - - if(data["access"]) - var/settings[0] - settings[++settings.len] = list("category" = "Target Red", "setting" = "check_synth", "value" = check_synth) // Could not get the UI to work with new vars specifically for lasertag turrets -Nalarac - settings[++settings.len] = list("category" = "Target Blue", "setting" = "check_weapons", "value" = check_weapons) // So I'm using these variables since they don't do anything else in this case - data["settings"] = settings - - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if(!ui) - ui = new(user, src, ui_key, "turret_control.tmpl", "Turret Controls", 500, 300) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) - -/obj/machinery/porta_turret/lasertag/Topic(href, href_list) - if(..()) - return 1 - - if(href_list["command"] && href_list["value"]) - var/value = text2num(href_list["value"]) - if(href_list["command"] == "enable") - enabled = value - //else if(href_list["command"] == "lethal") // VOREStation Removal of "Lethal" setting - it does nothing. Rykka did dis. - //lethal = value // VOREStation Removal of "Lethal" setting - it does nothing. Rykka did dis. - else if(href_list["command"] == "check_synth") - check_synth = value - else if(href_list["command"] == "check_weapons") - check_weapons = value - - return 1 +/obj/machinery/porta_turret/lasertag/tgui_data(mob/user) + var/list/data = list( + "locked" = isLocked(user), // does the current user have access? + "on" = enabled, // is turret turned on? + "lethal" = lethal, + "lethal_is_configurable" = lethal_is_configurable + ) + return data /obj/machinery/porta_turret/Initialize() //Sets up a spark system @@ -401,102 +377,99 @@ lethal_shot_sound = 'sound/weapons/eluger.ogg' shot_sound = 'sound/weapons/Taser.ogg' -/obj/machinery/porta_turret/proc/isLocked(mob/user) - if(ailock && issilicon(user)) - to_chat(user, "There seems to be a firewall preventing you from accessing this device.") - return 1 - - if(locked && !issilicon(user)) - to_chat(user, "Controls locked.") - return 1 - - return 0 - -/obj/machinery/porta_turret/attack_ai(mob/user) - if(isLocked(user)) - return - - ui_interact(user) - -/obj/machinery/porta_turret/attack_hand(mob/user) - if(isLocked(user)) - return - - ui_interact(user) - -/obj/machinery/porta_turret/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - var/data[0] - data["access"] = !isLocked(user) - data["locked"] = locked - data["enabled"] = enabled - data["is_lethal"] = 1 - data["lethal"] = lethal - - if(data["access"]) - var/settings[0] - settings[++settings.len] = list("category" = "Neutralize All Non-Synthetics", "setting" = "check_synth", "value" = check_synth) - settings[++settings.len] = list("category" = "Check Weapon Authorization", "setting" = "check_weapons", "value" = check_weapons) - settings[++settings.len] = list("category" = "Check Security Records", "setting" = "check_records", "value" = check_records) - settings[++settings.len] = list("category" = "Check Arrest Status", "setting" = "check_arrest", "value" = check_arrest) - settings[++settings.len] = list("category" = "Check Access Authorization", "setting" = "check_access", "value" = check_access) - settings[++settings.len] = list("category" = "Check misc. Lifeforms", "setting" = "check_anomalies", "value" = check_anomalies) - settings[++settings.len] = list("category" = "Neutralize All Entities", "setting" = "check_all", "value" = check_all) - settings[++settings.len] = list("category" = "Neutralize Downed Entities", "setting" = "check_down", "value" = check_down) - data["settings"] = settings - - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if(!ui) - ui = new(user, src, ui_key, "turret_control.tmpl", "Turret Controls", 500, 300) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) - /obj/machinery/porta_turret/proc/HasController() var/area/A = get_area(src) return A && A.turret_controls.len > 0 -/obj/machinery/porta_turret/CanUseTopic(var/mob/user) +/obj/machinery/porta_turret/proc/isLocked(mob/user) if(HasController()) - to_chat(user, "Turrets can only be controlled using the assigned turret controller.") - return STATUS_CLOSE + return TRUE + if(isrobot(user) || isAI(user)) + if(ailock) + to_chat(user, "There seems to be a firewall preventing you from accessing this device.") + return TRUE + else + return FALSE + if(isobserver(user)) + var/mob/observer/dead/D = user + if(D.can_admin_interact()) + return FALSE + else + return TRUE + if(locked) + return TRUE + return FALSE - if(isLocked(user)) - return STATUS_CLOSE +/obj/machinery/porta_turret/attack_ai(mob/user) + tgui_interact(user) +/obj/machinery/porta_turret/attack_ghost(mob/user) + tgui_interact(user) + +/obj/machinery/porta_turret/attack_hand(mob/user) + tgui_interact(user) + +/obj/machinery/porta_turret/tgui_interact(mob/user, datum/tgui/ui = null) + if(HasController()) + to_chat(user, "[src] can only be controlled using the assigned turret controller.") + return if(!anchored) - to_chat(user, "\The [src] has to be secured first!") - return STATUS_CLOSE + to_chat(user, "[src] has to be secured first!") + return + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "PortableTurret", name, 500, 400) + ui.open() - return ..() +/obj/machinery/porta_turret/tgui_data(mob/user) + var/list/data = list( + "locked" = isLocked(user), // does the current user have access? + "on" = enabled, + "targetting_is_configurable" = targetting_is_configurable, // If false, targetting settings don't show up + "lethal" = lethal, + "lethal_is_configurable" = lethal_is_configurable, + "check_weapons" = check_weapons, + "neutralize_noaccess" = check_access, + "neutralize_norecord" = check_records, + "neutralize_criminals" = check_arrest, + "neutralize_all" = check_all, + "neutralize_nonsynth" = check_synth, + "neutralize_unidentified" = check_anomalies, + "neutralize_down" = check_down, + ) + return data -/obj/machinery/porta_turret/Topic(href, href_list) +/obj/machinery/porta_turret/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) if(..()) - return 1 + return TRUE + if(isLocked(usr)) + return TRUE + . = TRUE - if(href_list["command"] && href_list["value"]) - var/value = text2num(href_list["value"]) - if(href_list["command"] == "enable") - enabled = value - else if(href_list["command"] == "lethal") - lethal = value - else if(href_list["command"] == "check_synth") - check_synth = value - else if(href_list["command"] == "check_weapons") - check_weapons = value - else if(href_list["command"] == "check_records") - check_records = value - else if(href_list["command"] == "check_arrest") - check_arrest = value - else if(href_list["command"] == "check_access") - check_access = value - else if(href_list["command"] == "check_anomalies") - check_anomalies = value - else if(href_list["command"] == "check_all") - check_all = value - else if(href_list["command"] == "check_down") - check_down = value - - return 1 + switch(action) + if("power") + enabled = !enabled + if("lethal") + if(lethal_is_configurable) + lethal = !lethal + if(targetting_is_configurable) + switch(action) + if("authweapon") + check_weapons = !check_weapons + if("authaccess") + check_access = !check_access + if("authnorecord") + check_records = !check_records + if("autharrest") + check_arrest = !check_arrest + if("authxeno") + check_anomalies = !check_anomalies + if("authsynth") + check_synth = !check_synth + if("authall") + check_all = !check_all + if("authdown") + check_down = !check_down /obj/machinery/porta_turret/power_change() if(powered()) @@ -929,6 +902,7 @@ var/check_weapons var/check_anomalies var/check_all + var/check_down var/ailock /obj/machinery/porta_turret/proc/setState(var/datum/turret_checks/TC) @@ -944,6 +918,7 @@ check_weapons = TC.check_weapons check_anomalies = TC.check_anomalies check_all = TC.check_all + check_down = TC.check_down ailock = TC.ailock power_change() diff --git a/code/game/machinery/requests_console.dm b/code/game/machinery/requests_console.dm index e87de196d9..86b339e6d5 100644 --- a/code/game/machinery/requests_console.dm +++ b/code/game/machinery/requests_console.dm @@ -104,7 +104,6 @@ var/list/obj/machinery/requests_console/allConsoles = list() /obj/machinery/requests_console/attack_hand(user as mob) if(..(user)) return - ui_interact(user) tgui_interact(user) /obj/machinery/requests_console/tgui_interact(mob/user, datum/tgui/ui) diff --git a/code/game/machinery/teleporter.dm b/code/game/machinery/teleporter.dm index 31dd9d2e13..cc8c262803 100644 --- a/code/game/machinery/teleporter.dm +++ b/code/game/machinery/teleporter.dm @@ -11,7 +11,7 @@ var/id = null var/one_time_use = 0 //Used for one-time-use teleport cards (such as clown planet coordinates.) //Setting this to 1 will set locked to null after a player enters the portal and will not allow hand-teles to open portals to that location. - var/datum/nano_module/program/teleport_control/teleport_control + var/datum/tgui_module/teleport_control/teleport_control /obj/machinery/computer/teleporter/New() id = "[rand(1000, 9999)]" @@ -44,7 +44,7 @@ teleport_control.station = station /obj/machinery/computer/teleporter/Destroy() - qdel_null(teleport_control) + QDEL_NULL(teleport_control) return ..() /obj/machinery/computer/teleporter/attackby(I as obj, mob/living/user as mob) @@ -96,108 +96,13 @@ attack_hand() /obj/machinery/computer/teleporter/attack_ai(mob/user) - ui_interact(user) + teleport_control.tgui_interact(user) /obj/machinery/computer/teleporter/attack_hand(mob/user) add_fingerprint(user) if(stat & (BROKEN|NOPOWER)) return - ui_interact(user) - -/obj/machinery/computer/teleporter/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - teleport_control.ui_interact(user, ui_key, ui, force_open) - -/obj/machinery/computer/teleporter/interact(mob/user) - teleport_control.ui_interact(user) - -////// -////// Nano-module for teleporter -////// -/datum/nano_module/program/teleport_control - name = "Teleporter Control" - var/locked_name = "Not Locked" - var/obj/item/locked = null - var/obj/machinery/teleport/station/station = null - var/obj/machinery/teleport/hub/hub = null - -/datum/nano_module/program/teleport_control/Topic(href, href_list) - if(..()) return 1 - - if(href_list["select_target"]) - var/list/L = list() - var/list/areaindex = list() - - for(var/obj/item/device/radio/beacon/R in all_beacons) - var/turf/T = get_turf(R) - if(!T) - continue - if(!(T.z in using_map.player_levels)) - continue - var/tmpname = T.loc.name - if(areaindex[tmpname]) - tmpname = "[tmpname] ([++areaindex[tmpname]])" - else - areaindex[tmpname] = 1 - L[tmpname] = R - - for (var/obj/item/weapon/implant/tracking/I in all_tracking_implants) - if(!I.implanted || !ismob(I.loc)) - continue - else - var/mob/M = I.loc - if(M.stat == 2) - if(M.timeofdeath + 6000 < world.time) - continue - var/turf/T = get_turf(M) - if(T) continue - if(T.z == 2) continue - var/tmpname = M.real_name - if(areaindex[tmpname]) - tmpname = "[tmpname] ([++areaindex[tmpname]])" - else - areaindex[tmpname] = 1 - L[tmpname] = I - - var/desc = input("Please select a location to lock in.", "Locking Menu") in L|null - if(!desc) - return 0 - if(get_dist(host, usr) > 1 && !issilicon(usr)) - return 0 - - locked = L[desc] - locked_name = desc - return 1 - - if(href_list["test_fire"]) - station?.testfire() - return 1 - - if(href_list["toggle_on"]) - if(!station) - return 0 - - if(station.engaged) - station.disengage() - else - station.engage() - - return 1 - -/datum/nano_module/program/teleport_control/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state) - var/list/data = host.initial_data() - - data["locked_name"] = locked_name ? locked_name : "No Target" - data["station_connected"] = station ? 1 : 0 - data["hub_connected"] = hub ? 1 : 0 - data["calibrated"] = hub ? hub.accurate : 0 - data["teleporter_on"] = station ? station.engaged : 0 - - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if(!ui) - ui = new(user, src, ui_key, "teleport_control.tmpl", "Teleport Control Console", 400, 500, state = state) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) + teleport_control.tgui_interact(user) /obj/machinery/computer/teleporter/verb/set_id(t as text) set category = "Object" @@ -211,14 +116,6 @@ id = t return -/proc/find_loc(obj/R as obj) - if(!R) return null - var/turf/T = R.loc - while(!istype(T, /turf)) - T = T.loc - if(!T || istype(T, /area)) return null - return T - ////// ////// Root of all the machinery ////// diff --git a/code/game/machinery/turret_control.dm b/code/game/machinery/turret_control.dm index a3d10db557..ad55fe14a1 100644 --- a/code/game/machinery/turret_control.dm +++ b/code/game/machinery/turret_control.dm @@ -11,31 +11,35 @@ desc = "Used to control a room's automated defenses." icon = 'icons/obj/machines/turret_control.dmi' icon_state = "control_standby" - anchored = 1 - density = 0 - var/enabled = 0 - var/lethal = 0 - var/locked = 1 + anchored = TRUE + density = FALSE + var/enabled = FALSE + var/lethal = FALSE + var/lethal_is_configurable = TRUE + var/locked = TRUE var/area/control_area //can be area name, path or nothing. - var/check_arrest = 1 //checks if the perp is set to arrest - var/check_records = 1 //checks if a security record exists at all - var/check_weapons = 0 //checks if it can shoot people that have a weapon they aren't authorized to have - var/check_access = 1 //if this is active, the turret shoots everything that does not meet the access requirements - var/check_anomalies = 1 //checks if it can shoot at unidentified lifeforms (ie xenos) - var/check_synth = 0 //if active, will shoot at anything not an AI or cyborg - var/check_all = 0 //If active, will shoot at anything. - var/ailock = 0 //Silicons cannot use this + var/targetting_is_configurable = TRUE // if false, you cannot change who this turret attacks via its UI + var/check_arrest = TRUE //checks if the perp is set to arrest + var/check_records = TRUE //checks if a security record exists at all + var/check_weapons = FALSE //checks if it can shoot people that have a weapon they aren't authorized to have + var/check_access = TRUE //if this is active, the turret shoots everything that does not meet the access requirements + var/check_anomalies = TRUE //checks if it can shoot at unidentified lifeforms (ie xenos) + var/check_synth = FALSE //if active, will shoot at anything not an AI or cyborg + var/check_all = FALSE //If active, will shoot at anything. + var/check_down = TRUE //If active, won't shoot laying targets. + var/ailock = FALSE //Silicons cannot use this + var/syndicate = FALSE req_access = list(access_ai_upload) /obj/machinery/turretid/stun - enabled = 1 + enabled = TRUE icon_state = "control_stun" /obj/machinery/turretid/lethal - enabled = 1 - lethal = 1 + enabled = TRUE + lethal = TRUE icon_state = "control_kill" /obj/machinery/turretid/Destroy() @@ -67,21 +71,24 @@ . = ..() /obj/machinery/turretid/proc/isLocked(mob/user) - if(ailock && issilicon(user)) - to_chat(user, "There seems to be a firewall preventing you from accessing this device.") - return 1 + if(isrobot(user) || isAI(user)) + if(ailock) + to_chat(user, "There seems to be a firewall preventing you from accessing this device.") + return TRUE + else + return FALSE - if(locked && !issilicon(user)) - to_chat(user, "Access denied.") - return 1 + if(isobserver(user)) + var/mob/observer/dead/D = user + if(D.can_admin_interact()) + return FALSE + else + return TRUE - return 0 + if(locked) + return TRUE -/obj/machinery/turretid/CanUseTopic(mob/user) - if(isLocked(user)) - return STATUS_CLOSE - - return ..() + return FALSE /obj/machinery/turretid/attackby(obj/item/weapon/W, mob/user) if(stat & BROKEN) @@ -100,77 +107,80 @@ /obj/machinery/turretid/emag_act(var/remaining_charges, var/mob/user) if(!emagged) to_chat(user, "You short out the turret controls' access analysis module.") - emagged = 1 - locked = 0 - ailock = 0 - return 1 + emagged = TRUE + locked = FALSE + ailock = FALSE + return TRUE /obj/machinery/turretid/attack_ai(mob/user as mob) - if(isLocked(user)) - return + tgui_interact(user) - ui_interact(user) +/obj/machinery/turretid/attack_ghost(mob/user as mob) + tgui_interact(user) /obj/machinery/turretid/attack_hand(mob/user as mob) - if(isLocked(user)) + tgui_interact(user) + +/obj/machinery/turretid/tgui_interact(mob/user, datum/tgui/ui = null) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "PortableTurret", name) // 500, 400 + ui.open() + +/obj/machinery/turretid/tgui_data(mob/user) + var/list/data = list( + "locked" = isLocked(user), // does the current user have access? + "on" = enabled, + "targetting_is_configurable" = targetting_is_configurable, + "lethal" = lethal, + "lethal_is_configurable" = lethal_is_configurable, + "check_weapons" = check_weapons, + "neutralize_noaccess" = check_access, + "one_access" = FALSE, + "selectedAccess" = list(), + "access_is_configurable" = FALSE, + "neutralize_norecord" = check_records, + "neutralize_criminals" = check_arrest, + "neutralize_nonsynth" = check_synth, + "neutralize_all" = check_all, + "neutralize_unidentified" = check_anomalies, + "neutralize_down" = check_down, + ) + return data + +/obj/machinery/turretid/tgui_act(action, params) + if(..()) + return + if(isLocked(usr)) return - ui_interact(user) + . = TRUE + switch(action) + if("power") + enabled = !enabled + if("lethal") + if(lethal_is_configurable) + lethal = !lethal + if(targetting_is_configurable) + switch(action) + if("authweapon") + check_weapons = !check_weapons + if("authaccess") + check_access = !check_access + if("authnorecord") + check_records = !check_records + if("autharrest") + check_arrest = !check_arrest + if("authxeno") + check_anomalies = !check_anomalies + if("authsynth") + check_synth = !check_synth + if("authall") + check_all = !check_all + if("authdown") + check_down = !check_down -/obj/machinery/turretid/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - var/data[0] - data["access"] = !isLocked(user) - data["locked"] = locked - data["enabled"] = enabled - data["is_lethal"] = 1 - data["lethal"] = lethal - - if(data["access"]) - var/settings[0] - settings[++settings.len] = list("category" = "Neutralize All Non-Synthetics", "setting" = "check_synth", "value" = check_synth) - settings[++settings.len] = list("category" = "Check Weapon Authorization", "setting" = "check_weapons", "value" = check_weapons) - settings[++settings.len] = list("category" = "Check Security Records", "setting" = "check_records", "value" = check_records) - settings[++settings.len] = list("category" = "Check Arrest Status", "setting" = "check_arrest", "value" = check_arrest) - settings[++settings.len] = list("category" = "Check Access Authorization", "setting" = "check_access", "value" = check_access) - settings[++settings.len] = list("category" = "Check misc. Lifeforms", "setting" = "check_anomalies", "value" = check_anomalies) - settings[++settings.len] = list("category" = "Neutralize All Entities", "setting" = "check_all", "value" = check_all) - - data["settings"] = settings - - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if(!ui) - ui = new(user, src, ui_key, "turret_control.tmpl", "Turret Controls", 500, 300) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) - -/obj/machinery/turretid/Topic(href, href_list) - if(..()) - return 1 - - if(href_list["command"] && href_list["value"]) - var/value = text2num(href_list["value"]) - if(href_list["command"] == "enable") - enabled = value - else if(href_list["command"] == "lethal") - lethal = value - else if(href_list["command"] == "check_synth") - check_synth = value - else if(href_list["command"] == "check_weapons") - check_weapons = value - else if(href_list["command"] == "check_records") - check_records = value - else if(href_list["command"] == "check_arrest") - check_arrest = value - else if(href_list["command"] == "check_access") - check_access = value - else if(href_list["command"] == "check_anomalies") - check_anomalies = value - else if(href_list["command"] == "check_all") - check_all = value - - updateTurrets() - return 1 + updateTurrets() /obj/machinery/turretid/proc/updateTurrets() var/datum/turret_checks/TC = new @@ -183,10 +193,11 @@ TC.check_weapons = check_weapons TC.check_anomalies = check_anomalies TC.check_all = check_all + TC.check_down = check_down TC.ailock = ailock if(istype(control_area)) - for (var/obj/machinery/porta_turret/aTurret in control_area) + for(var/obj/machinery/porta_turret/aTurret in control_area) aTurret.setState(TC) update_icon() diff --git a/code/game/machinery/vitals_monitor.dm b/code/game/machinery/vitals_monitor.dm index a26c3ff706..e6d1ba5811 100644 --- a/code/game/machinery/vitals_monitor.dm +++ b/code/game/machinery/vitals_monitor.dm @@ -144,6 +144,6 @@ if(!istype(user)) return - if(CanInteract(user, physical_state)) + if(CanInteract(user, GLOB.tgui_physical_state)) beep = !beep to_chat(user, "You turn the sound on \the [src] [beep ? "on" : "off"].") diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index a6aafb577e..b1aa1fb888 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -559,12 +559,12 @@ target.attack_hand(src.occupant) return 1 if(istype(target, /obj/machinery/embedded_controller)) - target.ui_interact(src.occupant) + target.tgui_interact(src.occupant) return 1 return 0 -/obj/mecha/contents_nano_distance(var/src_object, var/mob/living/user) - . = user.shared_living_nano_distance(src_object) //allow them to interact with anything they can interact with normally. +/obj/mecha/contents_tgui_distance(var/src_object, var/mob/living/user) + . = user.shared_living_tgui_distance(src_object) //allow them to interact with anything they can interact with normally. if(. != STATUS_INTERACTIVE) //Allow interaction with the mecha or anything that is part of the mecha if(src_object == src || (src_object in src)) diff --git a/code/game/objects/items/devices/communicator/communicator.dm b/code/game/objects/items/devices/communicator/communicator.dm index edcfde3074..358ef3b61b 100644 --- a/code/game/objects/items/devices/communicator/communicator.dm +++ b/code/game/objects/items/devices/communicator/communicator.dm @@ -233,7 +233,6 @@ var/global/list/obj/item/device/communicator/all_communicators = list() initialize_exonet(user) alert_called = 0 update_icon() - ui_interact(user) // TGUITODO: Remove tgui_interact(user) if(video_source) watch_video(user) diff --git a/code/game/objects/items/devices/hacktool.dm b/code/game/objects/items/devices/hacktool.dm index da1c165e9e..b221ff875c 100644 --- a/code/game/objects/items/devices/hacktool.dm +++ b/code/game/objects/items/devices/hacktool.dm @@ -5,7 +5,7 @@ var/in_hack_mode = 0 var/list/known_targets var/list/supported_types - var/datum/topic_state/default/must_hack/hack_state + var/datum/tgui_state/default/must_hack/hack_state /obj/item/device/multitool/hacktool/New() ..() @@ -39,7 +39,8 @@ if(!attempt_hack(user, A)) return 0 - A.ui_interact(user, state = hack_state) + // Note, if you ever want to expand supported_types, you must manually add the custom state argument to their tgui_interact + A.tgui_interact(user, custom_state = hack_state) return 1 /obj/item/device/multitool/hacktool/proc/attempt_hack(var/mob/user, var/atom/target) @@ -83,18 +84,18 @@ /obj/item/device/multitool/hacktool/proc/on_target_destroy(var/target) known_targets -= target -/datum/topic_state/default/must_hack +/datum/tgui_state/default/must_hack var/obj/item/device/multitool/hacktool/hacktool -/datum/topic_state/default/must_hack/New(var/hacktool) +/datum/tgui_state/default/must_hack/New(var/hacktool) src.hacktool = hacktool ..() -/datum/topic_state/default/must_hack/Destroy() +/datum/tgui_state/default/must_hack/Destroy() hacktool = null return ..() -/datum/topic_state/default/must_hack/can_use_topic(var/src_object, var/mob/user) +/datum/tgui_state/default/must_hack/can_use_topic(src_object, mob/user) if(!hacktool || !hacktool.in_hack_mode || !(src_object in hacktool.known_targets)) return STATUS_CLOSE return ..() diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index f1990c7fe2..d2511038dc 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -151,18 +151,10 @@ var/global/list/default_medbay_channels = list( return tgui_interact(user) -/obj/item/device/radio/ui_interact(mob/user, ui_key, datum/nanoui/ui, force_open, datum/nano_ui/master_ui, datum/topic_state/state) - log_runtime(EXCEPTION("Warning: [user] attempted to call ui_interact on radio [src] [type]. This is deprecated. Please update the caller to tgui_interact.")) - -/obj/item/device/radio/Topic(href, href_list) - if(href_list["track"]) - log_runtime(EXCEPTION("Warning: Topic() was improperly called on radio [src] [type], with the track href and \[[href] [json_encode(href_list)]]. Please update the caller to use tgui_act.")) - . = ..() - -/obj/item/device/radio/tgui_interact(mob/user, datum/tgui/ui) +/obj/item/device/radio/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui) ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, "Radio", name) + ui = new(user, src, "Radio", name, parent_ui) ui.open() /obj/item/device/radio/tgui_data(mob/user) diff --git a/code/game/objects/items/devices/tvcamera.dm b/code/game/objects/items/devices/tvcamera.dm index e8b6df0b98..acf4b7cc3a 100644 --- a/code/game/objects/items/devices/tvcamera.dm +++ b/code/game/objects/items/devices/tvcamera.dm @@ -54,7 +54,7 @@ popup.set_content(jointext(dat,null)) popup.open() -/obj/item/device/tvcamera/Topic(bred, href_list, state = physical_state) +/obj/item/device/tvcamera/Topic(bred, href_list, state = GLOB.tgui_physical_state) if(..()) return 1 if(href_list["channel"]) diff --git a/code/game/objects/items/weapons/id cards/syndicate_ids.dm b/code/game/objects/items/weapons/id cards/syndicate_ids.dm index 68cb0298a4..afb85ecb7a 100644 --- a/code/game/objects/items/weapons/id cards/syndicate_ids.dm +++ b/code/game/objects/items/weapons/id cards/syndicate_ids.dm @@ -6,8 +6,11 @@ var/electronic_warfare = 1 var/mob/registered_user = null + var/datum/tgui_module/agentcard/agentcard_module + /obj/item/weapon/card/id/syndicate/Initialize() . = ..() + agentcard_module = new(src) access = syndicate_access.Copy() /obj/item/weapon/card/id/syndicate/station_access/Initialize() @@ -15,6 +18,7 @@ access |= get_all_station_access() /obj/item/weapon/card/id/syndicate/Destroy() + QDEL_NULL(agentcard_module) unset_registered_user(registered_user) return ..() @@ -36,33 +40,12 @@ if(registered_user == user) switch(alert("Would you like edit the ID, or show it?","Show or Edit?", "Edit","Show")) if("Edit") - ui_interact(user) + agentcard_module.tgui_interact(user) if("Show") ..() else ..() -/obj/item/weapon/card/id/syndicate/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - var/data[0] - var/entries[0] - entries[++entries.len] = list("name" = "Age", "value" = age) - entries[++entries.len] = list("name" = "Appearance", "value" = "Set") - entries[++entries.len] = list("name" = "Assignment", "value" = assignment) - entries[++entries.len] = list("name" = "Blood Type", "value" = blood_type) - entries[++entries.len] = list("name" = "DNA Hash", "value" = dna_hash) - entries[++entries.len] = list("name" = "Fingerprint Hash", "value" = fingerprint_hash) - entries[++entries.len] = list("name" = "Name", "value" = registered_name) - entries[++entries.len] = list("name" = "Photo", "value" = "Update") - entries[++entries.len] = list("name" = "Sex", "value" = sex) - entries[++entries.len] = list("name" = "Factory Reset", "value" = "Use With Care") - data["electronic_warfare"] = electronic_warfare - data["entries"] = entries - - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - ui = new(user, src, ui_key, "agent_id_card.tmpl", "Fake ID", 600, 400) - ui.set_initial_data(data) - ui.open() /obj/item/weapon/card/id/syndicate/proc/register_user(var/mob/user) if(!istype(user) || user == registered_user) @@ -79,114 +62,6 @@ registered_user.unregister(OBSERVER_EVENT_DESTROY, src) registered_user = null -/obj/item/weapon/card/id/syndicate/CanUseTopic(mob/user) - if(user != registered_user) - return STATUS_CLOSE - return ..() - -/obj/item/weapon/card/id/syndicate/Topic(href, href_list, var/datum/topic_state/state) - if(..()) - return 1 - - var/user = usr - if(href_list["electronic_warfare"]) - electronic_warfare = text2num(href_list["electronic_warfare"]) - to_chat(user, "Electronic warfare [electronic_warfare ? "enabled" : "disabled"].") - else if(href_list["set"]) - switch(href_list["set"]) - if("Age") - var/new_age = input(user,"What age would you like to put on this card?","Agent Card Age", age) as null|num - if(!isnull(new_age) && CanUseTopic(user, state)) - if(new_age < 0) - age = initial(age) - else - age = new_age - to_chat(user, "Age has been set to '[age]'.") - . = 1 - if("Appearance") - var/datum/card_state/choice = input(user, "Select the appearance for this card.", "Agent Card Appearance") as null|anything in id_card_states() - if(choice && CanUseTopic(user, state)) - src.icon_state = choice.icon_state - src.item_state = choice.item_state - to_chat(usr, "Appearance changed to [choice].") - . = 1 - if("Assignment") - var/new_job = sanitize(input(user,"What assignment would you like to put on this card?\nChanging assignment will not grant or remove any access levels.","Agent Card Assignment", assignment) as null|text) - if(!isnull(new_job) && CanUseTopic(user, state)) - src.assignment = new_job - to_chat(user, "Occupation changed to '[new_job]'.") - update_name() - . = 1 - if("Blood Type") - var/default = blood_type - if(default == initial(blood_type) && ishuman(user)) - var/mob/living/carbon/human/H = user - if(H.dna) - default = H.dna.b_type - var/new_blood_type = sanitize(input(user,"What blood type would you like to be written on this card?","Agent Card Blood Type",default) as null|text) - if(!isnull(new_blood_type) && CanUseTopic(user, state)) - src.blood_type = new_blood_type - to_chat(user, "Blood type changed to '[new_blood_type]'.") - . = 1 - if("DNA Hash") - var/default = dna_hash - if(default == initial(dna_hash) && ishuman(user)) - var/mob/living/carbon/human/H = user - if(H.dna) - default = H.dna.unique_enzymes - var/new_dna_hash = sanitize(input(user,"What DNA hash would you like to be written on this card?","Agent Card DNA Hash",default) as null|text) - if(!isnull(new_dna_hash) && CanUseTopic(user, state)) - src.dna_hash = new_dna_hash - to_chat(user, "DNA hash changed to '[new_dna_hash]'.") - . = 1 - if("Fingerprint Hash") - var/default = fingerprint_hash - if(default == initial(fingerprint_hash) && ishuman(user)) - var/mob/living/carbon/human/H = user - if(H.dna) - default = md5(H.dna.uni_identity) - var/new_fingerprint_hash = sanitize(input(user,"What fingerprint hash would you like to be written on this card?","Agent Card Fingerprint Hash",default) as null|text) - if(!isnull(new_fingerprint_hash) && CanUseTopic(user, state)) - src.fingerprint_hash = new_fingerprint_hash - to_chat(user, "Fingerprint hash changed to '[new_fingerprint_hash]'.") - . = 1 - if("Name") - var/new_name = sanitizeName(input(user,"What name would you like to put on this card?","Agent Card Name", registered_name) as null|text) - if(!isnull(new_name) && CanUseTopic(user, state)) - src.registered_name = new_name - update_name() - to_chat(user, "Name changed to '[new_name]'.") - . = 1 - if("Photo") - set_id_photo(user) - to_chat(user, "Photo changed.") - . = 1 - if("Sex") - var/new_sex = sanitize(input(user,"What sex would you like to put on this card?","Agent Card Sex", sex) as null|text) - if(!isnull(new_sex) && CanUseTopic(user, state)) - src.sex = new_sex - to_chat(user, "Sex changed to '[new_sex]'.") - . = 1 - if("Factory Reset") - if(alert("This will factory reset the card, including access and owner. Continue?", "Factory Reset", "No", "Yes") == "Yes" && CanUseTopic(user, state)) - age = initial(age) - access = syndicate_access.Copy() - assignment = initial(assignment) - blood_type = initial(blood_type) - dna_hash = initial(dna_hash) - electronic_warfare = initial(electronic_warfare) - fingerprint_hash = initial(fingerprint_hash) - icon_state = initial(icon_state) - name = initial(name) - registered_name = initial(registered_name) - unset_registered_user() - sex = initial(sex) - to_chat(user, "All information has been deleted from \the [src].") - . = 1 - - // Always update the UI, or buttons will spin indefinitely - SSnanoui.update_uis(src) - /var/global/list/id_card_states /proc/id_card_states() if(!id_card_states) diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index 9bca1c2933..688236eda8 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -42,7 +42,7 @@ old_turf.unregister_dangerous_object(src) new_turf.register_dangerous_object(src) -/obj/Topic(href, href_list, var/datum/topic_state/state = default_state) +/obj/Topic(href, href_list, var/datum/tgui_state/state = GLOB.tgui_default_state) if(usr && ..()) return 1 @@ -55,7 +55,7 @@ CouldNotUseTopic(usr) return 1 -/obj/CanUseTopic(var/mob/user, var/datum/topic_state/state = default_state) +/obj/CanUseTopic(var/mob/user, var/datum/tgui_state/state = GLOB.tgui_default_state) if(user.CanUseObjTopic(src)) return ..() to_chat(user, "[bicon(src)]Access Denied!") @@ -69,7 +69,7 @@ return 1 /obj/proc/CouldUseTopic(var/mob/user) - var/atom/host = nano_host() + var/atom/host = tgui_host() host.add_hiddenprint(user) /obj/proc/CouldNotUseTopic(var/mob/user) @@ -135,7 +135,6 @@ in_use = 0 /obj/attack_ghost(mob/user) - ui_interact(user) tgui_interact(user) ..() diff --git a/code/game/objects/structures/janicart.dm b/code/game/objects/structures/janicart.dm index fad039445e..a6dc8e42ac 100644 --- a/code/game/objects/structures/janicart.dm +++ b/code/game/objects/structures/janicart.dm @@ -20,8 +20,90 @@ GLOBAL_LIST_BOILERPLATE(all_janitorial_carts, /obj/structure/janitorialcart) var/has_items = FALSE var/dismantled = TRUE var/signs = 0 //maximum capacity hardcoded below + var/list/tgui_icons = list() + var/static/list/equippable_item_whitelist +/obj/structure/janitorialcart/proc/equip_janicart_item(mob/user, obj/item/I) + if(!equippable_item_whitelist) + equippable_item_whitelist = typecacheof(list( + /obj/item/weapon/storage/bag/trash, + /obj/item/weapon/mop, + /obj/item/weapon/reagent_containers/spray, + /obj/item/device/lightreplacer, + /obj/item/clothing/suit/caution, + )) + + if(!is_type_in_typecache(I, equippable_item_whitelist)) + to_chat(user, "There's no room in [src] for [I].") + return FALSE + + if(!user.unEquip(I, 0, src)) + to_chat(user, "[I] is stuck to your hand.") + return FALSE + + if(istype(I, /obj/item/weapon/storage/bag/trash)) + if(mybag) + to_chat(user, "[src] already has \an [I].") + return FALSE + mybag = I + setTguiIcon("mybag", mybag) + + else if(istype(I, /obj/item/weapon/mop)) + if(mymop) + to_chat(user, "[src] already has \an [I].") + return FALSE + mymop = I + setTguiIcon("mymop", mymop) + + else if(istype(I, /obj/item/weapon/reagent_containers/spray)) + if(myspray) + to_chat(user, "[src] already has \an [I].") + return FALSE + myspray = I + setTguiIcon("myspray", myspray) + + else if(istype(I, /obj/item/device/lightreplacer)) + if(myreplacer) + to_chat(user, "[src] already has \an [I].") + return FALSE + myreplacer = I + setTguiIcon("myreplacer", myreplacer) + + else if(istype(I, /obj/item/clothing/suit/caution)) + if(signs < 4) + signs++ + setTguiIcon("signs", I) + else + to_chat(user, "[src] can't hold any more signs.") + return FALSE + else + // This may look like duplicate code, but it's important that we don't call unEquip *and* warn the user if + // something horrible goes wrong. (this else is never supposed to happen) + to_chat(user, "There's no room in [src] for [I].") + return FALSE + + update_icon() + to_chat(user, "You put [I] into [src].") + return TRUE + +/obj/structure/janitorialcart/proc/setTguiIcon(key, atom/A) + if(!istype(A) || !key) + return + + var/icon/F = getFlatIcon(A, defdir = SOUTH, no_anim = TRUE) + tgui_icons["[key]"] = "'data:image/png;base64,[icon2base64(F)]'" + SStgui.update_uis(src) + +/obj/structure/janitorialcart/proc/nullTguiIcon(key) + if(!key) + return + tgui_icons.Remove(key) + SStgui.update_uis(src) + +/obj/structure/janitorialcart/proc/clearTguiIcons() + tgui_icons.Cut() + SStgui.update_uis(src) /obj/structure/janitorialcart/Destroy() QDEL_NULL(mybag) @@ -29,6 +111,7 @@ GLOBAL_LIST_BOILERPLATE(all_janitorial_carts, /obj/structure/janitorialcart) QDEL_NULL(myspray) QDEL_NULL(myreplacer) QDEL_NULL(mybucket) + clearTguiIcons() return ..() /obj/structure/janitorialcart/examine(mob/user) @@ -43,6 +126,7 @@ GLOBAL_LIST_BOILERPLATE(all_janitorial_carts, /obj/structure/janitorialcart) if (istype(O, /obj/structure/mopbucket) && !mybucket) O.forceMove(src) mybucket = O + setTguiIcon("mybucket", mybucket) to_chat(user, "You mount the [O] on the janicart.") update_icon() else @@ -70,38 +154,19 @@ GLOBAL_LIST_BOILERPLATE(all_janitorial_carts, /obj/structure/janitorialcart) return 1 else if(istype(I, /obj/item/weapon/reagent_containers/spray) && !myspray) - user.unEquip(I, 0, src) - myspray = I - update_icon() - updateUsrDialog() - to_chat(user, "You put [I] into [src].") + equip_janicart_item(user, I) return 1 else if(istype(I, /obj/item/device/lightreplacer) && !myreplacer) - user.unEquip(I, 0, src) - myreplacer = I - update_icon() - updateUsrDialog() - to_chat(user, "You put [I] into [src].") + equip_janicart_item(user, I) return 1 else if(istype(I, /obj/item/weapon/storage/bag/trash) && !mybag) - user.unEquip(I, 0, src) - mybag = I - update_icon() - updateUsrDialog() - to_chat(user, "You put [I] into [src].") + equip_janicart_item(user, I) return 1 else if(istype(I, /obj/item/clothing/suit/caution)) - if(signs < 4) - user.unEquip(I, 0, src) - signs++ - update_icon() - updateUsrDialog() - to_chat(user, "You put [I] into [src].") - else - to_chat(user, "[src] can't hold any more signs.") + equip_janicart_item(user, I) return 1 else if(mybag) @@ -124,16 +189,7 @@ GLOBAL_LIST_BOILERPLATE(all_janitorial_carts, /obj/structure/janitorialcart) if(user.incapacitated() || !Adjacent(user)) return var/obj/I = usr.get_active_hand() if(istype(I, /obj/item/weapon/mop)) - if(!mymop) - usr.drop_from_inventory(I,src) - mymop = I - update_icon() - updateUsrDialog() - to_chat(usr, "You put [I] into [src].") - update_icon() - else - to_chat(usr, "The cart already has a mop attached") - return + equip_janicart_item(user, I) else if(istype(I, /obj/item/weapon/reagent_containers) && mybucket) var/obj/item/weapon/reagent_containers/C = I C.afterattack(mybucket, usr, 1) @@ -141,75 +197,95 @@ GLOBAL_LIST_BOILERPLATE(all_janitorial_carts, /obj/structure/janitorialcart) /obj/structure/janitorialcart/attack_hand(mob/user) - ui_interact(user) + tgui_interact(user) return -/obj/structure/janitorialcart/ui_interact(var/mob/user, var/ui_key = "main", var/datum/nanoui/ui = null, var/force_open = TRUE) - var/data[0] - data["name"] = capitalize(name) - data["bag"] = mybag ? capitalize(mybag.name) : null - data["bucket"] = mybucket ? capitalize(mybucket.name) : null - data["mop"] = mymop ? capitalize(mymop.name) : null - data["spray"] = myspray ? capitalize(myspray.name) : null - data["replacer"] = myreplacer ? capitalize(myreplacer.name) : null - data["signs"] = signs ? "[signs] sign\s" : null - - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) +/obj/structure/janitorialcart/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "janitorcart.tmpl", "Janitorial cart", 240, 160) - ui.set_initial_data(data) + ui = new(user, src, "JanitorCart", name) // 240, 160 + ui.set_autoupdate(FALSE) ui.open() +/obj/structure/janitorialcart/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state) + var/list/data = ..() -/obj/structure/janitorialcart/Topic(href, href_list) - if(!in_range(src, usr)) - return - if(!isliving(usr)) - return - var/mob/living/user = usr + data["mybag"] = mybag ? capitalize(mybag.name) : null + data["mybucket"] = mybucket ? capitalize(mybucket.name) : null + data["mymop"] = mymop ? capitalize(mymop.name) : null + data["myspray"] = myspray ? capitalize(myspray.name) : null + data["myreplacer"] = myreplacer ? capitalize(myreplacer.name) : null + data["signs"] = signs ? "[signs] sign\s" : null - if(href_list["take"]) - switch(href_list["take"]) - if("garbage") - if(mybag) - user.put_in_hands(mybag) - to_chat(user, "You take [mybag] from [src].") - mybag = null - if("mop") - if(mymop) - user.put_in_hands(mymop) - to_chat(user, "You take [mymop] from [src].") - mymop = null - if("spray") - if(myspray) - user.put_in_hands(myspray) - to_chat(user, "You take [myspray] from [src].") - myspray = null - if("replacer") - if(myreplacer) - user.put_in_hands(myreplacer) - to_chat(user, "You take [myreplacer] from [src].") - myreplacer = null - if("sign") - if(signs) - var/obj/item/clothing/suit/caution/Sign = locate() in src - if(Sign) - user.put_in_hands(Sign) - to_chat(user, "You take \a [Sign] from [src].") - signs-- - else - warning("[src] signs ([signs]) didn't match contents") - signs = 0 - if("bucket") - if(mybucket) - mybucket.forceMove(get_turf(user)) - to_chat(user, "You unmount [mybucket] from [src].") - mybucket = null + data["icons"] = tgui_icons + return data + +/obj/structure/janitorialcart/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) + if(..()) + return TRUE + + var/obj/item/I = usr.get_active_hand() + + switch(action) + if("bag") + if(mybag) + usr.put_in_hands(mybag) + to_chat(usr, "You take [mybag] from [src].") + mybag = null + nullTguiIcon("mybag") + else if(is_type_in_typecache(I, equippable_item_whitelist)) + equip_janicart_item(usr, I) + if("mop") + if(mymop) + usr.put_in_hands(mymop) + to_chat(usr, "You take [mymop] from [src].") + mymop = null + nullTguiIcon("mymop") + else if(is_type_in_typecache(I, equippable_item_whitelist)) + equip_janicart_item(usr, I) + if("spray") + if(myspray) + usr.put_in_hands(myspray) + to_chat(usr, "You take [myspray] from [src].") + myspray = null + nullTguiIcon("myspray") + else if(is_type_in_typecache(I, equippable_item_whitelist)) + equip_janicart_item(usr, I) + if("replacer") + if(myreplacer) + usr.put_in_hands(myreplacer) + to_chat(usr, "You take [myreplacer] from [src].") + myreplacer = null + nullTguiIcon("myreplacer") + else if(is_type_in_typecache(I, equippable_item_whitelist)) + equip_janicart_item(usr, I) + if("sign") + if(istype(I, /obj/item/clothing/suit/caution) && signs < 4) + equip_janicart_item(usr, I) + else if(signs) + var/obj/item/clothing/suit/caution/sign = locate() in src + if(sign) + usr.put_in_hands(sign) + to_chat(usr, "You take \a [sign] from [src].") + signs-- + if(!signs) + nullTguiIcon("signs") + else + to_chat(usr, "[src] doesn't have any signs left.") + if("bucket") + if(mybucket) + mybucket.forceMove(get_turf(usr)) + to_chat(usr, "You unmount [mybucket] from [src].") + mybucket = null + nullTguiIcon("mybucket") + else + to_chat(usr, "((Drag and drop a mop bucket onto [src] to equip it.))") + return FALSE + else + return FALSE update_icon() - updateUsrDialog() - - + return TRUE /obj/structure/janitorialcart/update_icon() overlays.Cut() @@ -229,11 +305,6 @@ GLOBAL_LIST_BOILERPLATE(all_janitorial_carts, /obj/structure/janitorialcart) if(signs) overlays += "cart_sign[signs]" - - - - - //This is called if the cart is caught in an explosion, or destroyed by weapon fire /obj/structure/janitorialcart/proc/spill(var/chance = 100) var/turf/dropspot = get_turf(src) @@ -275,6 +346,7 @@ GLOBAL_LIST_BOILERPLATE(all_janitorial_carts, /obj/structure/janitorialcart) mybag = null update_icon() + clearTguiIcons() diff --git a/code/game/objects/structures/under_wardrobe.dm b/code/game/objects/structures/under_wardrobe.dm index cb5db5411d..c919663eaa 100644 --- a/code/game/objects/structures/under_wardrobe.dm +++ b/code/game/objects/structures/under_wardrobe.dm @@ -67,7 +67,7 @@ if(!UWC) return var/datum/category_item/underwear/selected_underwear = input(H, "Choose underwear:", "Choose underwear", H.all_underwear[UWC.name]) as null|anything in UWC.items - if(selected_underwear && CanUseTopic(H, default_state)) + if(selected_underwear && CanUseTopic(H, GLOB.tgui_default_state)) H.all_underwear[UWC.name] = selected_underwear H.hide_underwear[UWC.name] = FALSE . = TRUE diff --git a/code/modules/asset_cache/asset_list_items.dm b/code/modules/asset_cache/asset_list_items.dm index df3e695628..bb43597d95 100644 --- a/code/modules/asset_cache/asset_list_items.dm +++ b/code/modules/asset_cache/asset_list_items.dm @@ -433,45 +433,6 @@ // Insert("polycrystal", 'icons/obj/telescience.dmi', "polycrystal") // ..() -/datum/asset/nanoui - var/list/common = list() - - var/list/common_dirs = list( - "nano/css/", - "nano/images/", - "nano/images/modular_computers/", - "nano/js/" - ) - var/list/template_dirs = list( - "nano/templates/" - ) - -/datum/asset/nanoui/register() - // Crawl the directories to find files. - for(var/path in common_dirs) - var/list/filenames = flist(path) - for(var/filename in filenames) - if(copytext(filename, length(filename)) != "/") // Ignore directories. - if(fexists(path + filename)) - common[filename] = fcopy_rsc(path + filename) - register_asset(filename, common[filename]) - // Combine all templates into a single bundle. - var/list/template_data = list() - for(var/path in template_dirs) - var/list/filenames = flist(path) - for(var/filename in filenames) - if(copytext(filename, length(filename) - 4) == ".tmpl") // Ignore directories. - template_data[filename] = file2text(path + filename) - var/template_bundle = "function nanouiTemplateBundle(){return [json_encode(template_data)];}" - var/fname = "data/nano_templates_bundle.js" - fdel(fname) - text2file(template_bundle, fname) - register_asset("nano_templates_bundle.js", fcopy_rsc(fname)) - fdel(fname) - -/datum/asset/nanoui/send(client) - send_asset_list(client, common) - //Pill sprites for UIs /datum/asset/chem_master var/assets = list() @@ -522,4 +483,29 @@ /datum/asset/spritesheet/sheetmaterials/register() InsertAll("", 'icons/obj/stacks.dmi') - ..() \ No newline at end of file + ..() + +// Nanomaps +/datum/asset/simple/nanomaps + // It REALLY doesnt matter too much if these arent up to date + // They are relatively big + assets = list( + "southern_cross_nanomap_z1.png" = 'icons/_nanomaps/southern_cross_nanomap_z1.png', + "southern_cross_nanomap_z10.png" = 'icons/_nanomaps/southern_cross_nanomap_z10.png', + "southern_cross_nanomap_z2.png" = 'icons/_nanomaps/southern_cross_nanomap_z2.png', + "southern_cross_nanomap_z3.png" = 'icons/_nanomaps/southern_cross_nanomap_z3.png', + "southern_cross_nanomap_z5.png" = 'icons/_nanomaps/southern_cross_nanomap_z5.png', + "southern_cross_nanomap_z6.png" = 'icons/_nanomaps/southern_cross_nanomap_z6.png', + "tether_nanomap_z1.png" = 'icons/_nanomaps/tether_nanomap_z1.png', + "tether_nanomap_z10.png" = 'icons/_nanomaps/tether_nanomap_z10.png', + "tether_nanomap_z13.png" = 'icons/_nanomaps/tether_nanomap_z13.png', + "tether_nanomap_z14.png" = 'icons/_nanomaps/tether_nanomap_z14.png', + "tether_nanomap_z2.png" = 'icons/_nanomaps/tether_nanomap_z2.png', + "tether_nanomap_z3.png" = 'icons/_nanomaps/tether_nanomap_z3.png', + "tether_nanomap_z4.png" = 'icons/_nanomaps/tether_nanomap_z4.png', + "tether_nanomap_z5.png" = 'icons/_nanomaps/tether_nanomap_z5.png', + "tether_nanomap_z6.png" = 'icons/_nanomaps/tether_nanomap_z6.png', + "tether_nanomap_z7.png" = 'icons/_nanomaps/tether_nanomap_z7.png', + "tether_nanomap_z8.png" = 'icons/_nanomaps/tether_nanomap_z8.png', + "tether_nanomap_z9.png" = 'icons/_nanomaps/tether_nanomap_z9.png', + ) \ No newline at end of file diff --git a/code/modules/clothing/glasses/hud_vr.dm b/code/modules/clothing/glasses/hud_vr.dm index 613c09e91e..718b9e6908 100644 --- a/code/modules/clothing/glasses/hud_vr.dm +++ b/code/modules/clothing/glasses/hud_vr.dm @@ -8,8 +8,6 @@ var/obj/item/clothing/glasses/hud/omni/hud = null var/mode = "civ" icon_state = "glasses" - var/datum/nano_module/arscreen - var/arscreen_path var/datum/tgui_module/tgarscreen var/tgarscreen_path var/flash_prot = 0 //0 for none, 1 for flash weapon protection, 2 for welder protection @@ -18,34 +16,24 @@ /obj/item/clothing/glasses/omnihud/New() ..() - if(arscreen_path) - arscreen = new arscreen_path(src) if(tgarscreen_path) tgarscreen = new tgarscreen_path(src) /obj/item/clothing/glasses/omnihud/Destroy() - QDEL_NULL(arscreen) QDEL_NULL(tgarscreen) . = ..() /obj/item/clothing/glasses/omnihud/dropped() - if(arscreen) - SSnanoui.close_uis(src) if(tgarscreen) SStgui.close_uis(src) ..() /obj/item/clothing/glasses/omnihud/emp_act(var/severity) - if(arscreen) - SSnanoui.close_uis(src) if(tgarscreen) SStgui.close_uis(src) - var/disconnect_ar = arscreen var/disconnect_tgar = tgarscreen - arscreen = null tgarscreen = null spawn(20 SECONDS) - arscreen = disconnect_ar tgarscreen = disconnect_tgar //extra fun for non-sci variants; a small chance flip the state to the dumb 3d glasses when EMP'd diff --git a/code/modules/clothing/spacesuits/rig/modules/computer.dm b/code/modules/clothing/spacesuits/rig/modules/computer.dm index cf055ae9c0..fbf08479f4 100644 --- a/code/modules/clothing/spacesuits/rig/modules/computer.dm +++ b/code/modules/clothing/spacesuits/rig/modules/computer.dm @@ -23,7 +23,7 @@ to_chat(usr, "Your module is not installed in a hardsuit.") return - module.holder.ui_interact(usr, nano_state = contained_state) + module.holder.tgui_interact(usr, custom_state = GLOB.tgui_contained_state) /obj/item/rig_module/ai_container diff --git a/code/modules/clothing/spacesuits/rig/modules/specific/ai_container.dm b/code/modules/clothing/spacesuits/rig/modules/specific/ai_container.dm index e6848a66d0..4f7dfef043 100644 --- a/code/modules/clothing/spacesuits/rig/modules/specific/ai_container.dm +++ b/code/modules/clothing/spacesuits/rig/modules/specific/ai_container.dm @@ -134,7 +134,7 @@ if(!target) if(ai_card) if(istype(ai_card,/obj/item/device/aicard)) - ai_card.tgui_interact(H, custom_state = deep_inventory_state) + ai_card.tgui_interact(H, custom_state = GLOB.tgui_deep_inventory_state) else eject_ai(H) update_verb_holder() diff --git a/code/modules/economy/Accounts_DB.dm b/code/modules/economy/Accounts_DB.dm index 9e116ecf60..68f71184e9 100644 --- a/code/modules/economy/Accounts_DB.dm +++ b/code/modules/economy/Accounts_DB.dm @@ -15,7 +15,7 @@ var/const/fund_cap = 1000000 /obj/machinery/account_database/proc/get_access_level() - if (!held_card) + if(!held_card) return 0 if(access_cent_captain in held_card.access) return 2 @@ -53,19 +53,24 @@ O.loc = src held_card = O - SSnanoui.update_uis(src) + SStgui.update_uis(src) attack_hand(user) /obj/machinery/account_database/attack_hand(mob/user as mob) if(stat & (NOPOWER|BROKEN)) return - ui_interact(user) + tgui_interact(user) -/obj/machinery/account_database/ui_interact(mob/user, ui_key="main", var/datum/nanoui/ui = null, var/force_open = 1) - user.set_machine(src) +/obj/machinery/account_database/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "AccountsTerminal", name) + ui.open() + + +/obj/machinery/account_database/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state) + var/list/data = ..() - var/data[0] - data["src"] = "\ref[src]" data["id_inserted"] = !!held_card data["id_card"] = held_card ? text("[held_card.registered_name], [held_card.assignment]") : "-----" data["access_level"] = get_access_level() @@ -73,10 +78,14 @@ data["creating_new_account"] = creating_new_account data["detailed_account_view"] = !!detailed_account_view data["station_account_number"] = station_account.account_number - data["transactions"] = null - data["accounts"] = null - if (detailed_account_view) + data["account_number"] = null + data["owner_name"] = null + data["money"] = null + data["suspended"] = null + data["transactions"] = list() + + if(detailed_account_view) data["account_number"] = detailed_account_view.account_number data["owner_name"] = detailed_account_view.owner_name data["money"] = detailed_account_view.money @@ -92,11 +101,10 @@ "amount" = T.amount, \ "source_terminal" = T.source_terminal))) - if (trx.len > 0) - data["transactions"] = trx + data["transactions"] = trx - var/list/accounts[0] - for(var/i=1, i<=all_money_accounts.len, i++) + var/list/accounts = list() + for(var/i in 1 to LAZYLEN(all_money_accounts)) var/datum/money_account/D = all_money_accounts[i] if(D.offmap) continue @@ -106,174 +114,168 @@ "suspended"=D.suspended ? "SUSPENDED" : "",\ "account_index"=i))) - if (accounts.len > 0) - data["accounts"] = accounts + data["accounts"] = accounts - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - ui = new(user, src, ui_key, "accounts_terminal.tmpl", src.name, 400, 640) - ui.set_initial_data(data) - ui.open() + return data -/obj/machinery/account_database/Topic(href, href_list) +/obj/machinery/account_database/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) if(..()) - return 1 + return TRUE - var/datum/nanoui/ui = SSnanoui.get_open_ui(usr, src, "main") + switch(action) + if("create_account") + creating_new_account = 1 - if(href_list["choice"]) - switch(href_list["choice"]) - if("create_account") - creating_new_account = 1 + if("add_funds") + var/amount = input("Enter the amount you wish to add", "Silently add funds") as num + if(detailed_account_view) + detailed_account_view.money = min(detailed_account_view.money + amount, fund_cap) - if("add_funds") - var/amount = input("Enter the amount you wish to add", "Silently add funds") as num - if(detailed_account_view) - detailed_account_view.money = min(detailed_account_view.money + amount, fund_cap) + if("remove_funds") + var/amount = input("Enter the amount you wish to remove", "Silently remove funds") as num + if(detailed_account_view) + detailed_account_view.money = max(detailed_account_view.money - amount, -fund_cap) - if("remove_funds") - var/amount = input("Enter the amount you wish to remove", "Silently remove funds") as num - if(detailed_account_view) - detailed_account_view.money = max(detailed_account_view.money - amount, -fund_cap) + if("toggle_suspension") + if(detailed_account_view) + detailed_account_view.suspended = !detailed_account_view.suspended + callHook("change_account_status", list(detailed_account_view)) - if("toggle_suspension") - if(detailed_account_view) - detailed_account_view.suspended = !detailed_account_view.suspended - callHook("change_account_status", list(detailed_account_view)) + if("finalise_create_account") + var/account_name = params["holder_name"] + var/starting_funds = max(text2num(params["starting_funds"]), 0) - if("finalise_create_account") - var/account_name = href_list["holder_name"] - var/starting_funds = max(text2num(href_list["starting_funds"]), 0) + starting_funds = CLAMP(starting_funds, 0, station_account.money) // Not authorized to put the station in debt. + starting_funds = min(starting_funds, fund_cap) // Not authorized to give more than the fund cap. - starting_funds = CLAMP(starting_funds, 0, station_account.money) // Not authorized to put the station in debt. - starting_funds = min(starting_funds, fund_cap) // Not authorized to give more than the fund cap. + create_account(account_name, starting_funds, src) + if(starting_funds > 0) + //subtract the money + station_account.money -= starting_funds - create_account(account_name, starting_funds, src) - if(starting_funds > 0) - //subtract the money - station_account.money -= starting_funds - - //create a transaction log entry - var/trx = create_transation(account_name, "New account activation", "([starting_funds])") - station_account.transaction_log.Add(trx) - - creating_new_account = 0 - ui.close() + //create a transaction log entry + var/trx = create_transation(account_name, "New account activation", "([starting_funds])") + station_account.transaction_log.Add(trx) creating_new_account = 0 - if("insert_card") - if(held_card) - held_card.loc = src.loc - if(ishuman(usr) && !usr.get_active_hand()) - usr.put_in_hands(held_card) - held_card = null + creating_new_account = 0 + if("insert_card") + if(held_card) + held_card.loc = src.loc - else - var/obj/item/I = usr.get_active_hand() - if (istype(I, /obj/item/weapon/card/id)) - var/obj/item/weapon/card/id/C = I - usr.drop_item() - C.loc = src - held_card = C + if(ishuman(usr) && !usr.get_active_hand()) + usr.put_in_hands(held_card) + held_card = null - if("view_account_detail") - var/index = text2num(href_list["account_index"]) - if(index && index <= all_money_accounts.len) - detailed_account_view = all_money_accounts[index] + else + var/obj/item/I = usr.get_active_hand() + if(istype(I, /obj/item/weapon/card/id)) + var/obj/item/weapon/card/id/C = I + usr.drop_item() + C.loc = src + held_card = C - if("view_accounts_list") - detailed_account_view = null - creating_new_account = 0 + if("view_account_detail") + var/index = text2num(params["account_index"]) + if(index && index <= all_money_accounts.len) + detailed_account_view = all_money_accounts[index] - if("revoke_payroll") - var/funds = detailed_account_view.money - var/account_trx = create_transation(station_account.owner_name, "Revoke payroll", "([funds])") - var/station_trx = create_transation(detailed_account_view.owner_name, "Revoke payroll", funds) + if("view_accounts_list") + detailed_account_view = null + creating_new_account = 0 - station_account.money += funds - detailed_account_view.money = 0 + if("revoke_payroll") + var/funds = detailed_account_view.money + var/account_trx = create_transation(station_account.owner_name, "Revoke payroll", "([funds])") + var/station_trx = create_transation(detailed_account_view.owner_name, "Revoke payroll", funds) - detailed_account_view.transaction_log.Add(account_trx) - station_account.transaction_log.Add(station_trx) + station_account.money += funds + detailed_account_view.money = 0 - callHook("revoke_payroll", list(detailed_account_view)) + detailed_account_view.transaction_log.Add(account_trx) + station_account.transaction_log.Add(station_trx) - if("print") - var/text - var/obj/item/weapon/paper/P = new(loc) - if (detailed_account_view) - P.name = "account #[detailed_account_view.account_number] details" - var/title = "Account #[detailed_account_view.account_number] Details" - text = {" - [accounting_letterhead(title)] - Holder: [detailed_account_view.owner_name]
- Balance: $[detailed_account_view.money]
- Status: [detailed_account_view.suspended ? "Suspended" : "Active"]
- Transactions: ([detailed_account_view.transaction_log.len])
- - - - - - - - - - - - "} + callHook("revoke_payroll", list(detailed_account_view)) - for (var/datum/transaction/T in detailed_account_view.transaction_log) - text += {" - - - - - - - - "} + if("print") + print() - text += {" - -
TimestampTargetReasonValueTerminal
[T.date] [T.time][T.target_name][T.purpose][T.amount][T.source_terminal]
- "} + return TRUE - else - P.name = "financial account list" - text = {" - [accounting_letterhead("Financial Account List")] +/obj/machinery/account_database/proc/print() + var/text + var/obj/item/weapon/paper/P = new(loc) + if(detailed_account_view) + P.name = "account #[detailed_account_view.account_number] details" + var/title = "Account #[detailed_account_view.account_number] Details" + text = {" + [accounting_letterhead(title)] + Holder: [detailed_account_view.owner_name]
+ Balance: $[detailed_account_view.money]
+ Status: [detailed_account_view.suspended ? "Suspended" : "Active"]
+ Transactions: ([detailed_account_view.transaction_log.len])
+ + + + + + + + + + + + "} -
TimestampTargetReasonValueTerminal
- - - - - - - - - - "} + for (var/datum/transaction/T in detailed_account_view.transaction_log) + text += {" + + + + + + + + "} - for(var/i=1, i<=all_money_accounts.len, i++) - var/datum/money_account/D = all_money_accounts[i] - text += {" - - - - - - - "} + text += {" + +
Account NumberHolderBalanceStatus
[T.date] [T.time][T.target_name][T.purpose][T.amount][T.source_terminal]
#[D.account_number][D.owner_name]$[D.money][D.suspended ? "Suspended" : "Active"]
+ "} - text += {" - - - "} + else + P.name = "financial account list" + text = {" + [accounting_letterhead("Financial Account List")] - P.info = text - state("The terminal prints out a report.") + + + + + + + + + + + "} - return 1 + for(var/i=1, i<=all_money_accounts.len, i++) + var/datum/money_account/D = all_money_accounts[i] + text += {" + + + + + + + "} + + text += {" + +
Account NumberHolderBalanceStatus
#[D.account_number][D.owner_name]$[D.money][D.suspended ? "Suspended" : "Active"]
+ "} + + P.info = text + state("The terminal prints out a report.") \ No newline at end of file diff --git a/code/modules/integrated_electronics/core/assemblies/device.dm b/code/modules/integrated_electronics/core/assemblies/device.dm index 3170393fc3..8500f4dafc 100644 --- a/code/modules/integrated_electronics/core/assemblies/device.dm +++ b/code/modules/integrated_electronics/core/assemblies/device.dm @@ -78,7 +78,7 @@ output.assembly = src /obj/item/device/electronic_assembly/device/check_interactivity(mob/user) - if(!CanInteract(user, state = deep_inventory_state)) + if(!CanInteract(user, state = GLOB.tgui_deep_inventory_state)) return 0 return 1 diff --git a/code/modules/integrated_electronics/core/pins.dm b/code/modules/integrated_electronics/core/pins.dm index ddc0b06f8a..c194b4a8a2 100644 --- a/code/modules/integrated_electronics/core/pins.dm +++ b/code/modules/integrated_electronics/core/pins.dm @@ -40,8 +40,8 @@ D [1]/ || holder = null . = ..() -/datum/integrated_io/nano_host() - return holder.nano_host() +/datum/integrated_io/tgui_host() + return holder.tgui_host() /datum/integrated_io/proc/data_as_type(var/as_type) diff --git a/code/modules/integrated_electronics/core/special_pins/list_pin.dm b/code/modules/integrated_electronics/core/special_pins/list_pin.dm index 77d83f82b5..4eeb756cd0 100644 --- a/code/modules/integrated_electronics/core/special_pins/list_pin.dm +++ b/code/modules/integrated_electronics/core/special_pins/list_pin.dm @@ -117,7 +117,7 @@ /datum/integrated_io/list/display_pin_type() return IC_FORMAT_LIST -/datum/integrated_io/list/Topic(href, href_list, state = interactive_state) +/datum/integrated_io/list/Topic(href, href_list, state = GLOB.tgui_always_state) if(!holder.check_interactivity(usr)) return if(..()) diff --git a/code/modules/integrated_electronics/core/tools.dm b/code/modules/integrated_electronics/core/tools.dm index 79533bfe25..5bf48370e2 100644 --- a/code/modules/integrated_electronics/core/tools.dm +++ b/code/modules/integrated_electronics/core/tools.dm @@ -115,7 +115,7 @@ /obj/item/device/integrated_electronics/debugger/attack_self(mob/user) var/type_to_use = input("Please choose a type to use.","[src] type setting") as null|anything in list("string","number","ref", "null") - if(!CanInteract(user, physical_state)) + if(!CanInteract(user, GLOB.tgui_physical_state)) return var/new_data = null @@ -124,13 +124,13 @@ accepting_refs = 0 new_data = input("Now type in a string.","[src] string writing") as null|text new_data = sanitizeSafe(new_data, MAX_MESSAGE_LEN, 0, 0) - if(istext(new_data) && CanInteract(user, physical_state)) + if(istext(new_data) && CanInteract(user, GLOB.tgui_physical_state)) data_to_write = new_data to_chat(user, "You set \the [src]'s memory to \"[new_data]\".") if("number") accepting_refs = 0 new_data = input("Now type in a number.","[src] number writing") as null|num - if(isnum(new_data) && CanInteract(user, physical_state)) + if(isnum(new_data) && CanInteract(user, GLOB.tgui_physical_state)) data_to_write = new_data to_chat(user, "You set \the [src]'s memory to [new_data].") if("ref") diff --git a/code/modules/integrated_electronics/subtypes/input.dm b/code/modules/integrated_electronics/subtypes/input.dm index a084633642..9c140cedae 100644 --- a/code/modules/integrated_electronics/subtypes/input.dm +++ b/code/modules/integrated_electronics/subtypes/input.dm @@ -54,7 +54,7 @@ /obj/item/integrated_circuit/input/numberpad/ask_for_input(mob/user) var/new_input = input(user, "Enter a number, please.","Number pad", get_pin_data(IC_OUTPUT, 1)) as null|num - if(isnum(new_input) && CanInteract(user, physical_state)) + if(isnum(new_input) && CanInteract(user, GLOB.tgui_physical_state)) set_pin_data(IC_OUTPUT, 1, new_input) push_data() activate_pin(1) @@ -73,7 +73,7 @@ /obj/item/integrated_circuit/input/textpad/ask_for_input(mob/user) var/new_input = input(user, "Enter some words, please.","Number pad", get_pin_data(IC_OUTPUT, 1)) as null|text - if(istext(new_input) && CanInteract(user, physical_state)) + if(istext(new_input) && CanInteract(user, GLOB.tgui_physical_state)) set_pin_data(IC_OUTPUT, 1, new_input) push_data() activate_pin(1) @@ -92,7 +92,7 @@ /obj/item/integrated_circuit/input/colorpad/ask_for_input(mob/user) var/new_color = input(user, "Enter a color, please.", "Color pad", get_pin_data(IC_OUTPUT, 1)) as color|null - if(new_color && CanInteract(user, physical_state)) + if(new_color && CanInteract(user, GLOB.tgui_physical_state)) set_pin_data(IC_OUTPUT, 1, new_color) push_data() activate_pin(1) diff --git a/code/modules/integrated_electronics/subtypes/memory.dm b/code/modules/integrated_electronics/subtypes/memory.dm index 630136e7d0..90cb23de35 100644 --- a/code/modules/integrated_electronics/subtypes/memory.dm +++ b/code/modules/integrated_electronics/subtypes/memory.dm @@ -89,7 +89,7 @@ /obj/item/integrated_circuit/memory/constant/attack_self(mob/user) var/datum/integrated_io/O = outputs[1] var/type_to_use = input("Please choose a type to use.","[src] type setting") as null|anything in list("string","number","ref", "null") - if(!CanInteract(user, physical_state)) + if(!CanInteract(user, GLOB.tgui_physical_state)) return var/new_data = null @@ -97,13 +97,13 @@ if("string") accepting_refs = 0 new_data = input("Now type in a string.","[src] string writing") as null|text - if(istext(new_data) && CanInteract(user, physical_state)) + if(istext(new_data) && CanInteract(user, GLOB.tgui_physical_state)) O.data = new_data to_chat(user, "You set \the [src]'s memory to [O.display_data(O.data)].") if("number") accepting_refs = 0 new_data = input("Now type in a number.","[src] number writing") as null|num - if(isnum(new_data) && CanInteract(user, physical_state)) + if(isnum(new_data) && CanInteract(user, GLOB.tgui_physical_state)) O.data = new_data to_chat(user, "You set \the [src]'s memory to [O.display_data(O.data)].") if("ref") diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 031ad576cd..0c20f6bf31 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -20,7 +20,6 @@ var/list/ai_verbs_default = list( /mob/living/silicon/ai/proc/ai_call_shuttle, /mob/living/silicon/ai/proc/ai_camera_track, /mob/living/silicon/ai/proc/ai_camera_list, - /mob/living/silicon/ai/proc/ai_roster, /mob/living/silicon/ai/proc/ai_checklaws, /mob/living/silicon/ai/proc/toggle_camera_light, /mob/living/silicon/ai/proc/take_image, @@ -355,12 +354,6 @@ var/list/ai_verbs_default = list( if(new_sprite) selected_sprite = new_sprite updateicon() -// this verb lets the ai see the stations manifest -/mob/living/silicon/ai/proc/ai_roster() - set category = "AI Commands" - set name = "Show Crew Manifest" - show_station_manifest() - /mob/living/silicon/ai/var/message_cooldown = 0 /mob/living/silicon/ai/proc/ai_announcement() set category = "AI Commands" diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm index 6e4cd0a401..cf135f9d55 100644 --- a/code/modules/mob/living/silicon/pai/pai.dm +++ b/code/modules/mob/living/silicon/pai/pai.dm @@ -213,7 +213,7 @@ medicalActive1 = null medicalActive2 = null medical_cannotfind = 0 - SSnanoui.update_uis(src) + SStgui.update_uis(src) to_chat(usr, "You reset your record-viewing software.") /mob/living/silicon/pai/cancel_camera() diff --git a/code/modules/mob/living/silicon/pai/software.dm b/code/modules/mob/living/silicon/pai/software.dm index 342e8d7f5c..cad5229097 100644 --- a/code/modules/mob/living/silicon/pai/software.dm +++ b/code/modules/mob/living/silicon/pai/software.dm @@ -41,27 +41,24 @@ var/global/list/default_pai_software = list() set category = "pAI Commands" set name = "Software Interface" - ui_interact(src) + tgui_interact(src) -/mob/living/silicon/pai/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1) - if(user != src) - if(ui) ui.set_status(STATUS_CLOSE, 0) - return +/mob/living/silicon/pai/tgui_state(mob/user) + return GLOB.tgui_self_state - if(ui_key != "main") - var/datum/pai_software/S = software[ui_key] - if(S && !S.toggle) - S.on_ui_interact(src, ui, force_open) - else - if(ui) ui.set_status(STATUS_CLOSE, 0) - return - - var/data[0] +/mob/living/silicon/pai/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "pAIInterface", "pAI Software Interface") + ui.open() +/mob/living/silicon/pai/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state) + var/list/data = ..() + // Software we have bought - var/bought_software[0] + var/list/bought_software = list() // Software we have not bought - var/not_bought_software[0] + var/list/not_bought_software = list() for(var/key in pai_software_by_key) var/datum/pai_software/S = pai_software_by_key[key] @@ -70,63 +67,52 @@ var/global/list/default_pai_software = list() software_data["id"] = S.id if(key in software) software_data["on"] = S.is_active(src) - bought_software[++bought_software.len] = software_data + bought_software.Add(list(software_data)) else software_data["ram"] = S.ram_cost - not_bought_software[++not_bought_software.len] = software_data + not_bought_software.Add(list(software_data)) data["bought"] = bought_software data["not_bought"] = not_bought_software data["available_ram"] = ram // Emotions - var/emotions[0] + var/list/emotions = list() for(var/name in pai_emotions) - var/emote[0] + var/list/emote = list() emote["name"] = name emote["id"] = pai_emotions[name] - emotions[++emotions.len] = emote + emotions.Add(list(emote)) data["emotions"] = emotions data["current_emotion"] = card.current_emotion - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - ui = new(user, src, ui_key, "pai_interface.tmpl", "pAI Software Interface", 450, 600) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) + return data -/mob/living/silicon/pai/Topic(href, href_list) - . = ..() - if(.) return +/mob/living/silicon/pai/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) + if(..()) + return TRUE - if(href_list["software"]) - var/soft = href_list["software"] - var/datum/pai_software/S = software[soft] - if(S.toggle) - S.toggle(src) - else - ui_interact(src, ui_key = soft) - S.tgui_interact(src) - return 1 + switch(action) + if("software") + var/soft = params["software"] + var/datum/pai_software/S = software[soft] + if(S.toggle) + S.toggle(src) + else + S.tgui_interact(src, parent_ui = ui) + return TRUE - else if(href_list["stopic"]) - var/soft = href_list["stopic"] - var/datum/pai_software/S = software[soft] - if(S) - return S.Topic(href, href_list) + if("purchase") + var/soft = params["purchase"] + var/datum/pai_software/S = pai_software_by_key[soft] + if(S && (ram >= S.ram_cost)) + ram -= S.ram_cost + software[S.id] = S + return TRUE - else if(href_list["purchase"]) - var/soft = href_list["purchase"] - var/datum/pai_software/S = pai_software_by_key[soft] - if(S && (ram >= S.ram_cost)) - ram -= S.ram_cost - software[S.id] = S - return 1 - - else if(href_list["image"]) - var/img = text2num(href_list["image"]) - if(1 <= img && img <= (pai_emotions.len)) - card.setEmotion(img) - return 1 + if("image") + var/img = text2num(params["image"]) + if(1 <= img && img <= (pai_emotions.len)) + card.setEmotion(img) + return TRUE diff --git a/code/modules/mob/living/silicon/pai/software_modules.dm b/code/modules/mob/living/silicon/pai/software_modules.dm index dd92edfdab..e518e74a4a 100644 --- a/code/modules/mob/living/silicon/pai/software_modules.dm +++ b/code/modules/mob/living/silicon/pai/software_modules.dm @@ -12,14 +12,11 @@ // Whether pAIs should automatically receive this module at no cost var/default = 0 - proc/on_ui_interact(mob/living/silicon/pai/user, datum/nanoui/ui=null, force_open=1) - return +/datum/pai_software/proc/toggle(mob/living/silicon/pai/user) + return - proc/toggle(mob/living/silicon/pai/user) - return - - proc/is_active(mob/living/silicon/pai/user) - return 0 +/datum/pai_software/proc/is_active(mob/living/silicon/pai/user) + return 0 /datum/pai_software/tgui_state(mob/user) return GLOB.tgui_always_state @@ -36,55 +33,58 @@ toggle = 0 default = 1 - on_ui_interact(mob/living/silicon/pai/user, datum/nanoui/ui=null, force_open=1) - var/data[0] +/datum/pai_software/directives/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "pAIDirectives", name, parent_ui) + ui.open() - data["master"] = user.master - data["dna"] = user.master_dna - data["prime"] = user.pai_law0 - data["supplemental"] = user.pai_laws +/datum/pai_software/directives/tgui_data(mob/living/silicon/pai/user, datum/tgui/ui, datum/tgui_state/state) + var/list/data = list() - ui = SSnanoui.try_update_ui(user, user, id, ui, data, force_open) - if(!ui) - // Don't copy-paste this unless you're making a pAI software module! - ui = new(user, user, id, "pai_directives.tmpl", "pAI Directives", 450, 600) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) + data["master"] = user.master + data["dna"] = user.master_dna + data["prime"] = user.pai_law0 + data["supplemental"] = user.pai_laws - Topic(href, href_list) - var/mob/living/silicon/pai/P = usr - if(!istype(P)) return + return data - if(href_list["getdna"]) - var/mob/living/M = P.loc - var/count = 0 +/datum/pai_software/directives/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) + var/mob/living/silicon/pai/P = usr + if(!istype(P)) + return TRUE + if(..()) + return TRUE - // Find the carrier - while(!istype(M, /mob/living)) - if(!M || !M.loc || count > 6) - //For a runtime where M ends up in nullspace (similar to bluespace but less colourful) - to_chat(src, "You are not being carried by anyone!") - return 0 - M = M.loc - count++ + if(action == "getdna") + var/mob/living/M = P.loc - // Check the carrier - var/datum/gender/TM = gender_datums[M.get_visible_gender()] - var/answer = input(M, "[P] is requesting a DNA sample from you. Will you allow it to confirm your identity?", "[P] Check DNA", "No") in list("Yes", "No") - if(answer == "Yes") - var/turf/T = get_turf_or_move(P.loc) - for (var/mob/v in viewers(T)) - v.show_message("[M] presses [TM.his] thumb against [P].", 3, "[P] makes a sharp clicking sound as it extracts DNA material from [M].", 2) - var/datum/dna/dna = M.dna - to_chat(P, "

[M]'s UE string : [dna.unique_enzymes]

") - if(dna.unique_enzymes == P.master_dna) - to_chat(P, "DNA is a match to stored Master DNA.") - else - to_chat(P, "DNA does not match stored Master DNA.") + var/count = 0 + // Find the carrier + while(!istype(M, /mob/living)) + if(!M || !M.loc || count > 6) + //For a runtime where M ends up in nullspace (similar to bluespace but less colourful) + to_chat(src, "You are not being carried by anyone!") + return 0 + M = M.loc + count++ + + // Check the carrier + var/datum/gender/TM = gender_datums[M.get_visible_gender()] + var/answer = input(M, "[P] is requesting a DNA sample from you. Will you allow it to confirm your identity?", "[P] Check DNA", "No") in list("Yes", "No") + if(answer == "Yes") + var/turf/T = get_turf(P.loc) + for (var/mob/v in viewers(T)) + v.show_message("[M] presses [TM.his] thumb against [P].", 3, "[P] makes a sharp clicking sound as it extracts DNA material from [M].", 2) + var/datum/dna/dna = M.dna + to_chat(P, "

[M]'s UE string : [dna.unique_enzymes]

") + if(dna.unique_enzymes == P.master_dna) + to_chat(P, "DNA is a match to stored Master DNA.") else - to_chat(P, "[M] does not seem like [TM.he] is going to provide a DNA sample willingly.") - return 1 + to_chat(P, "DNA does not match stored Master DNA.") + else + to_chat(P, "[M] does not seem like [TM.he] is going to provide a DNA sample willingly.") + return TRUE /datum/pai_software/radio_config name = "Radio Configuration" @@ -93,35 +93,8 @@ toggle = 0 default = 1 - on_ui_interact(mob/living/silicon/pai/user, datum/nanoui/ui = null, force_open = 1) - var/data[0] - - data["listening"] = user.radio.broadcasting - data["frequency"] = format_frequency(user.radio.frequency) - - var/channels[0] - for(var/ch_name in user.radio.channels) - var/ch_stat = user.radio.channels[ch_name] - var/ch_dat[0] - ch_dat["name"] = ch_name - // FREQ_LISTENING is const in /obj/item/device/radio - ch_dat["listening"] = !!(ch_stat & user.radio.FREQ_LISTENING) - channels[++channels.len] = ch_dat - - data["channels"] = channels - - ui = SSnanoui.try_update_ui(user, user, id, ui, data, force_open) - if(!ui) - ui = new(user, user, id, "pai_radio.tmpl", "Radio Configuration", 300, 150) - ui.set_initial_data(data) - ui.open() - - Topic(href, href_list) - var/mob/living/silicon/pai/P = usr - if(!istype(P)) return - - P.radio.Topic(href, href_list) - return 1 +/datum/pai_software/radio_config/tgui_interact(mob/living/silicon/pai/user, datum/tgui/ui, datum/tgui/parent_ui) + return user.radio.tgui_interact(user, parent_ui = parent_ui) /datum/pai_software/crew_manifest name = "Crew Manifest" @@ -129,20 +102,18 @@ id = "manifest" toggle = 0 - on_ui_interact(mob/living/silicon/pai/user, datum/nanoui/ui=null, force_open=1) +/datum/pai_software/crew_manifest/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "CrewManifest", name, parent_ui) + ui.open() + +/datum/pai_software/crew_manifest/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state) + var/list/data = ..() + if(data_core) data_core.get_manifest_list() - - var/data[0] - // This is dumb, but NanoUI breaks if it has no data to send - data["manifest"] = PDA_Manifest - - ui = SSnanoui.try_update_ui(user, user, id, ui, data, force_open) - if(!ui) - // Don't copy-paste this unless you're making a pAI software module! - ui = new(user, user, id, "crew_manifest.tmpl", "Crew Manifest", 450, 600) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) + data["manifest"] = PDA_Manifest + return data /datum/pai_software/messenger name = "Digital Messenger" @@ -151,7 +122,7 @@ toggle = 0 /datum/pai_software/messenger/tgui_interact(mob/living/silicon/pai/user, datum/tgui/ui, datum/tgui/parent_ui) - return user.pda.tgui_interact(user) + return user.pda.tgui_interact(user, parent_ui = parent_ui) /datum/pai_software/med_records name = "Medical Records" @@ -159,53 +130,55 @@ id = "med_records" toggle = 0 - on_ui_interact(mob/living/silicon/pai/user, datum/nanoui/ui=null, force_open=1) - var/data[0] +/datum/pai_software/med_records/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "pAIMedrecords", name, parent_ui) + ui.open() - var/records[0] - for(var/datum/data/record/general in sortRecord(data_core.general)) - var/record[0] - record["name"] = general.fields["name"] - record["ref"] = "\ref[general]" - records[++records.len] = record +/datum/pai_software/med_records/tgui_data(mob/living/silicon/pai/user, datum/tgui/ui, datum/tgui_state/state) + var/list/data = ..() + + var/list/records = list() + for(var/datum/data/record/general in sortRecord(data_core.general)) + var/list/record = list() + record["name"] = general.fields["name"] + record["ref"] = "\ref[general]" + records.Add(list(record)) - data["records"] = records + data["records"] = records - var/datum/data/record/G = user.medicalActive1 - var/datum/data/record/M = user.medicalActive2 - data["general"] = G ? G.fields : null - data["medical"] = M ? M.fields : null - data["could_not_find"] = user.medical_cannotfind + var/datum/data/record/G = user.medicalActive1 + var/datum/data/record/M = user.medicalActive2 + data["general"] = G ? G.fields : null + data["medical"] = M ? M.fields : null + data["could_not_find"] = user.medical_cannotfind - ui = SSnanoui.try_update_ui(user, user, id, ui, data, force_open) - if(!ui) - // Don't copy-paste this unless you're making a pAI software module! - ui = new(user, user, id, "pai_medrecords.tmpl", "Medical Records", 450, 600) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) + return data - Topic(href, href_list) - var/mob/living/silicon/pai/P = usr - if(!istype(P)) return +/datum/pai_software/med_records/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) + . = ..() + var/mob/living/silicon/pai/P = usr + if(!istype(P)) + return - if(href_list["select"]) - var/datum/data/record/record = locate(href_list["select"]) - if(record) - var/datum/data/record/R = record - var/datum/data/record/M = null - if (!( data_core.general.Find(R) )) - P.medical_cannotfind = 1 - else - P.medical_cannotfind = 0 - 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 - P.medicalActive1 = R - P.medicalActive2 = M - else + if(action == "select") + var/datum/data/record/record = locate(params["select"]) + if(record) + var/datum/data/record/R = record + var/datum/data/record/M = null + if (!( data_core.general.Find(R) )) P.medical_cannotfind = 1 - return 1 + else + P.medical_cannotfind = 0 + 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 + P.medicalActive1 = R + P.medicalActive2 = M + else + P.medical_cannotfind = 1 + return 1 /datum/pai_software/sec_records name = "Security Records" @@ -213,57 +186,59 @@ id = "sec_records" toggle = 0 - on_ui_interact(mob/living/silicon/pai/user, datum/nanoui/ui=null, force_open=1) - var/data[0] +/datum/pai_software/sec_records/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "pAISecrecords", name, parent_ui) + ui.open() - var/records[0] - for(var/datum/data/record/general in sortRecord(data_core.general)) - var/record[0] - record["name"] = general.fields["name"] - record["ref"] = "\ref[general]" - records[++records.len] = record +/datum/pai_software/sec_records/tgui_data(mob/living/silicon/pai/user, datum/tgui/ui, datum/tgui_state/state) + var/list/data = ..() + + var/list/records = list() + for(var/datum/data/record/general in sortRecord(data_core.general)) + var/list/record = list() + record["name"] = general.fields["name"] + record["ref"] = "\ref[general]" + records.Add(list(record)) - data["records"] = records + data["records"] = records - var/datum/data/record/G = user.securityActive1 - var/datum/data/record/S = user.securityActive2 - data["general"] = G ? G.fields : null - data["security"] = S ? S.fields : null - data["could_not_find"] = user.security_cannotfind + var/datum/data/record/G = user.securityActive1 + var/datum/data/record/S = user.securityActive2 + data["general"] = G ? G.fields : null + data["security"] = S ? S.fields : null + data["could_not_find"] = user.security_cannotfind - ui = SSnanoui.try_update_ui(user, user, id, ui, data, force_open) - if(!ui) - // Don't copy-paste this unless you're making a pAI software module! - ui = new(user, user, id, "pai_secrecords.tmpl", "Security Records", 450, 600) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) + return data - Topic(href, href_list) - var/mob/living/silicon/pai/P = usr - if(!istype(P)) return +/datum/pai_software/sec_records/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) + . = ..() + var/mob/living/silicon/pai/P = usr + if(!istype(P)) + return - if(href_list["select"]) - var/datum/data/record/record = locate(href_list["select"]) - if(record) - var/datum/data/record/R = record - var/datum/data/record/S = null - if (!( data_core.general.Find(R) )) - P.securityActive1 = null - P.securityActive2 = null - P.security_cannotfind = 1 - else - P.security_cannotfind = 0 - 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 - P.securityActive1 = R - P.securityActive2 = S - else + if(action == "select") + var/datum/data/record/record = locate(params["select"]) + if(record) + var/datum/data/record/R = record + var/datum/data/record/S = null + if (!( data_core.general.Find(R) )) P.securityActive1 = null P.securityActive2 = null P.security_cannotfind = 1 - return 1 + else + P.security_cannotfind = 0 + 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 + P.securityActive1 = R + P.securityActive2 = S + else + P.securityActive1 = null + P.securityActive2 = null + P.security_cannotfind = 1 + return TRUE /datum/pai_software/door_jack name = "Door Jack" @@ -271,47 +246,49 @@ id = "door_jack" toggle = 0 - on_ui_interact(mob/living/silicon/pai/user, datum/nanoui/ui=null, force_open=1) - var/data[0] +/datum/pai_software/door_jack/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "pAIDoorjack", "Door Jack", parent_ui) + ui.open() - data["cable"] = user.cable != null - data["machine"] = user.cable && (user.cable.machine != null) - data["inprogress"] = user.hackdoor != null - data["progress_a"] = round(user.hackprogress / 10) - data["progress_b"] = user.hackprogress % 10 - data["aborted"] = user.hack_aborted +/datum/pai_software/door_jack/tgui_data(mob/living/silicon/pai/user, datum/tgui/ui, datum/tgui_state/state) + var/list/data = ..() - ui = SSnanoui.try_update_ui(user, user, id, ui, data, force_open) - if(!ui) - // Don't copy-paste this unless you're making a pAI software module! - ui = new(user, user, id, "pai_doorjack.tmpl", "Door Jack", 300, 150) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) + data["cable"] = user.cable != null + data["machine"] = user.cable && (user.cable.machine != null) + data["inprogress"] = user.hackdoor != null + data["progress_a"] = round(user.hackprogress / 10) + data["progress_b"] = user.hackprogress % 10 + data["aborted"] = user.hack_aborted - Topic(href, href_list) - var/mob/living/silicon/pai/P = usr - if(!istype(P)) return + return data - if(href_list["jack"]) +/datum/pai_software/door_jack/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) + var/mob/living/silicon/pai/P = usr + if(!istype(P) || ..()) + return TRUE + + switch(action) + if("jack") if(P.cable && P.cable.machine) P.hackdoor = P.cable.machine P.hackloop() return 1 - else if(href_list["cancel"]) + if("cancel") P.hackdoor = null return 1 - else if(href_list["cable"]) - var/turf/T = get_turf_or_move(P.loc) + if("cable") + var/turf/T = get_turf(P) P.hack_aborted = 0 P.cable = new /obj/item/weapon/pai_cable(T) for(var/mob/M in viewers(T)) M.show_message("A port on [P] opens to reveal [P.cable], which promptly falls to the floor.", 3, - "You hear the soft click of something light and hard falling to the ground.", 2) + "You hear the soft click of something light and hard falling to the ground.", 2) return 1 /mob/living/silicon/pai/proc/hackloop() - var/turf/T = get_turf_or_move(src.loc) + var/turf/T = get_turf(src) for(var/mob/living/silicon/ai/AI in player_list) if(T.loc) to_chat(AI, "Network Alert: Brute-force encryption crack in progress in [T.loc].") @@ -345,134 +322,155 @@ id = "atmos_sense" toggle = 0 - on_ui_interact(mob/living/silicon/pai/user, datum/nanoui/ui=null, force_open=1) - var/data[0] +/datum/pai_software/atmosphere_sensor/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "pAIAtmos", name, parent_ui) + ui.open() - var/turf/T = get_turf_or_move(user.loc) - if(!T) - data["reading"] = 0 - data["pressure"] = 0 - data["temperature"] = 0 - data["temperatureC"] = 0 - data["gas"] = list() - else - var/datum/gas_mixture/env = T.return_air() - data["reading"] = 1 - var/pres = env.return_pressure() * 10 - data["pressure"] = "[round(pres/10)].[pres%10]" - data["temperature"] = round(env.temperature) - data["temperatureC"] = round(env.temperature-T0C) +/datum/pai_software/atmosphere_sensor/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state) + var/list/data = ..() - var/t_moles = env.total_moles - var/gases[0] - for(var/g in env.gas) - var/gas[0] - gas["name"] = gas_data.name[g] - gas["percent"] = round((env.gas[g] / t_moles) * 100) - gases[++gases.len] = gas - data["gas"] = gases + var/list/results = list() + var/turf/T = get_turf(user) + 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.gas["oxygen"]/total_moles + var/n2_level = environment.gas["nitrogen"]/total_moles + var/co2_level = environment.gas["carbon_dioxide"]/total_moles + var/phoron_level = environment.gas["phoron"]/total_moles + var/unknown_level = 1-(o2_level+n2_level+co2_level+phoron_level) - ui = SSnanoui.try_update_ui(user, user, id, ui, data, force_open) - if(!ui) - // Don't copy-paste this unless you're making a pAI software module! - ui = new(user, user, id, "pai_atmosphere.tmpl", "Atmosphere Sensor", 350, 300) - ui.set_initial_data(data) - ui.open() + // entry is what the element is describing + // Type identifies which unit or other special characters to use + // Val is the information reported + // Bad_high/_low are the values outside of which the entry reports as dangerous + // Poor_high/_low are the values outside of which the entry reports as unideal + // Values were extracted from the template itself + results = list( + list("entry" = "Pressure", "units" = "kPa", "val" = "[round(pressure,0.1)]", "bad_high" = 120, "poor_high" = 110, "poor_low" = 95, "bad_low" = 80), + list("entry" = "Temperature", "units" = "°C", "val" = "[round(environment.temperature-T0C,0.1)]", "bad_high" = 35, "poor_high" = 25, "poor_low" = 15, "bad_low" = 5), + list("entry" = "Oxygen", "units" = "kPa", "val" = "[round(o2_level*100,0.1)]", "bad_high" = 140, "poor_high" = 135, "poor_low" = 19, "bad_low" = 17), + list("entry" = "Nitrogen", "units" = "kPa", "val" = "[round(n2_level*100,0.1)]", "bad_high" = 105, "poor_high" = 85, "poor_low" = 50, "bad_low" = 40), + list("entry" = "Carbon Dioxide", "units" = "kPa", "val" = "[round(co2_level*100,0.1)]", "bad_high" = 10, "poor_high" = 5, "poor_low" = 0, "bad_low" = 0), + list("entry" = "Phoron", "units" = "kPa", "val" = "[round(phoron_level*100,0.01)]", "bad_high" = 0.5, "poor_high" = 0, "poor_low" = 0, "bad_low" = 0), + list("entry" = "Other", "units" = "kPa", "val" = "[round(unknown_level, 0.01)]", "bad_high" = 1, "poor_high" = 0.5, "poor_low" = 0, "bad_low" = 0) + ) + + if(isnull(results)) + results = list(list("entry" = "pressure", "units" = "kPa", "val" = "0", "bad_high" = 120, "poor_high" = 110, "poor_low" = 95, "bad_low" = 80)) + + data["aircontents"] = results + + return data /datum/pai_software/sec_hud name = "Security HUD" ram_cost = 20 id = "sec_hud" - toggle(mob/living/silicon/pai/user) - user.secHUD = !user.secHUD - user.plane_holder.set_vis(VIS_CH_ID, user.secHUD) - user.plane_holder.set_vis(VIS_CH_WANTED, user.secHUD) - user.plane_holder.set_vis(VIS_CH_IMPTRACK, user.secHUD) - user.plane_holder.set_vis(VIS_CH_IMPLOYAL, user.secHUD) - user.plane_holder.set_vis(VIS_CH_IMPCHEM, user.secHUD) +/datum/pai_software/sec_hud/toggle(mob/living/silicon/pai/user) + user.secHUD = !user.secHUD + user.plane_holder.set_vis(VIS_CH_ID, user.secHUD) + user.plane_holder.set_vis(VIS_CH_WANTED, user.secHUD) + user.plane_holder.set_vis(VIS_CH_IMPTRACK, user.secHUD) + user.plane_holder.set_vis(VIS_CH_IMPLOYAL, user.secHUD) + user.plane_holder.set_vis(VIS_CH_IMPCHEM, user.secHUD) - is_active(mob/living/silicon/pai/user) - return user.secHUD +/datum/pai_software/sec_hud/is_active(mob/living/silicon/pai/user) + return user.secHUD /datum/pai_software/med_hud name = "Medical HUD" ram_cost = 20 id = "med_hud" - toggle(mob/living/silicon/pai/user) - user.medHUD = !user.medHUD - user.plane_holder.set_vis(VIS_CH_STATUS, user.medHUD) - user.plane_holder.set_vis(VIS_CH_HEALTH, user.medHUD) +/datum/pai_software/med_hud/toggle(mob/living/silicon/pai/user) + user.medHUD = !user.medHUD + user.plane_holder.set_vis(VIS_CH_STATUS, user.medHUD) + user.plane_holder.set_vis(VIS_CH_HEALTH, user.medHUD) - is_active(mob/living/silicon/pai/user) - return user.medHUD +/datum/pai_software/med_hud/is_active(mob/living/silicon/pai/user) + return user.medHUD /datum/pai_software/translator name = "Universal Translator" ram_cost = 35 id = "translator" - toggle(mob/living/silicon/pai/user) - // Sol Common, Tradeband, Terminus and Gutter are added with New() and are therefore the current default, always active languages - user.translator_on = !user.translator_on - if(user.translator_on) - user.add_language(LANGUAGE_UNATHI) - user.add_language(LANGUAGE_SIIK) - user.add_language(LANGUAGE_AKHANI) - user.add_language(LANGUAGE_SKRELLIAN) - user.add_language(LANGUAGE_ZADDAT) - user.add_language(LANGUAGE_SCHECHI) - else - user.remove_language(LANGUAGE_UNATHI) - user.remove_language(LANGUAGE_SIIK) - user.remove_language(LANGUAGE_AKHANI) - user.remove_language(LANGUAGE_SKRELLIAN) - user.remove_language(LANGUAGE_ZADDAT) - user.remove_language(LANGUAGE_SCHECHI) +/datum/pai_software/translator/toggle(mob/living/silicon/pai/user) + // Sol Common, Tradeband, Terminus and Gutter are added with New() and are therefore the current default, always active languages + user.translator_on = !user.translator_on + if(user.translator_on) + user.add_language(LANGUAGE_UNATHI) + user.add_language(LANGUAGE_SIIK) + user.add_language(LANGUAGE_AKHANI) + user.add_language(LANGUAGE_SKRELLIAN) + user.add_language(LANGUAGE_ZADDAT) + user.add_language(LANGUAGE_SCHECHI) + else + user.remove_language(LANGUAGE_UNATHI) + user.remove_language(LANGUAGE_SIIK) + user.remove_language(LANGUAGE_AKHANI) + user.remove_language(LANGUAGE_SKRELLIAN) + user.remove_language(LANGUAGE_ZADDAT) + user.remove_language(LANGUAGE_SCHECHI) - is_active(mob/living/silicon/pai/user) - return user.translator_on +/datum/pai_software/translator/is_active(mob/living/silicon/pai/user) + return user.translator_on /datum/pai_software/signaller - name = "Remote Signaller" + name = "Remote Signaler" ram_cost = 5 id = "signaller" toggle = 0 - on_ui_interact(mob/living/silicon/pai/user, datum/nanoui/ui=null, force_open=1) - var/data[0] +/datum/pai_software/signaller/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "Signaler", "Signaler", parent_ui) + ui.open() - data["frequency"] = format_frequency(user.sradio.frequency) - data["code"] = user.sradio.code +/datum/pai_software/signaller/tgui_data(mob/living/silicon/pai/user, datum/tgui/ui, datum/tgui_state/state) + var/list/data = ..() + + var/obj/item/radio/integrated/signal/R = user.sradio - ui = SSnanoui.try_update_ui(user, user, id, ui, data, force_open) - if(!ui) - // Don't copy-paste this unless you're making a pAI software module! - ui = new(user, user, id, "pai_signaller.tmpl", "Signaller", 320, 150) - ui.set_initial_data(data) - ui.open() + data["frequency"] = R.frequency + data["minFrequency"] = RADIO_LOW_FREQ + data["maxFrequency"] = RADIO_HIGH_FREQ + data["code"] = R.code - Topic(href, href_list) - var/mob/living/silicon/pai/P = usr - if(!istype(P)) return + return data - if(href_list["send"]) - P.sradio.send_signal("ACTIVATE") - for(var/mob/O in hearers(1, P.loc)) - O.show_message("[bicon(P)] *beep* *beep*", 3, "*beep* *beep*", 2) - return 1 +/datum/pai_software/signaller/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) + if(..()) + return TRUE - else if(href_list["freq"]) - var/new_frequency = (P.sradio.frequency + text2num(href_list["freq"])) - if(new_frequency < PUBLIC_LOW_FREQ || new_frequency > PUBLIC_HIGH_FREQ) - new_frequency = sanitize_frequency(new_frequency) - P.sradio.set_frequency(new_frequency) - return 1 + var/mob/living/silicon/pai/user = usr + if(istype(user)) + var/obj/item/radio/integrated/signal/R = user.sradio - else if(href_list["code"]) - P.sradio.code += text2num(href_list["code"]) - P.sradio.code = round(P.sradio.code) - P.sradio.code = min(100, P.sradio.code) - P.sradio.code = max(1, P.sradio.code) - return 1 + switch(action) + if("signal") + spawn(0) + R.send_signal("ACTIVATE") + for(var/mob/O in hearers(1, R.loc)) + O.show_message("[bicon(R)] *beep* *beep*", 3, "*beep* *beep*", 2) + if("freq") + var/frequency = unformat_frequency(params["freq"]) + frequency = sanitize_frequency(frequency, RADIO_LOW_FREQ, RADIO_HIGH_FREQ) + R.set_frequency(frequency) + . = TRUE + if("code") + R.code = clamp(round(text2num(params["code"])), 1, 100) + . = TRUE + if("reset") + if(params["reset"] == "freq") + R.set_frequency(initial(R.frequency)) + else + R.code = initial(R.code) + . = TRUE diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index ad1e767aca..7d67ca3cc3 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -349,12 +349,6 @@ updatename() updateicon() -// this verb lets cyborgs see the stations manifest -/mob/living/silicon/robot/verb/cmd_station_manifest() - set category = "Robot Commands" - set name = "Show Crew Manifest" - show_station_manifest() - /mob/living/silicon/robot/proc/self_diagnosis() if(!is_component_functioning("diagnosis unit")) return null diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index b6cf748fb8..b9c2c60c47 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -153,18 +153,6 @@ show_malf_ai() ..() -// this function displays the stations manifest in a separate window -/mob/living/silicon/proc/show_station_manifest() - var/dat = "
" - if(!data_core) - to_chat(src, "There is no data to form a manifest with. Contact your Nanotrasen administrator.") - return - dat += data_core.get_manifest(1) //The 1 makes it monochrome. - - var/datum/browser/popup = new(src, "Crew Manifest", "Crew Manifest", 370, 420, src) - popup.set_content(dat) - popup.open() - //can't inject synths /mob/living/silicon/can_inject(var/mob/user, var/error_msg) if(error_msg) diff --git a/code/modules/mob/living/silicon/subystems.dm b/code/modules/mob/living/silicon/subystems.dm index be6a68591d..890f1a8b37 100644 --- a/code/modules/mob/living/silicon/subystems.dm +++ b/code/modules/mob/living/silicon/subystems.dm @@ -2,6 +2,7 @@ var/register_alarms = 1 var/datum/tgui_module/alarm_monitor/all/robot/alarm_monitor var/datum/tgui_module/atmos_control/robot/atmos_control + var/datum/tgui_module/crew_manifest/robot/crew_manifest var/datum/tgui_module/crew_monitor/robot/crew_monitor var/datum/tgui_module/law_manager/robot/law_manager var/datum/tgui_module/power_monitor/robot/power_monitor @@ -10,6 +11,7 @@ /mob/living/silicon var/list/silicon_subsystems = list( /mob/living/silicon/proc/subsystem_alarm_monitor, + /mob/living/silicon/proc/subsystem_crew_manifest, /mob/living/silicon/proc/subsystem_law_manager ) @@ -17,6 +19,7 @@ silicon_subsystems = list( /mob/living/silicon/proc/subsystem_alarm_monitor, /mob/living/silicon/proc/subsystem_atmos_control, + /mob/living/silicon/proc/subsystem_crew_manifest, /mob/living/silicon/proc/subsystem_crew_monitor, /mob/living/silicon/proc/subsystem_law_manager, /mob/living/silicon/proc/subsystem_power_monitor, @@ -30,6 +33,7 @@ /mob/living/silicon/proc/init_subsystems() alarm_monitor = new(src) atmos_control = new(src) + crew_manifest = new(src) crew_monitor = new(src) law_manager = new(src) power_monitor = new(src) @@ -60,6 +64,15 @@ atmos_control.tgui_interact(usr) +/******************** +* Crew Manifest * +********************/ +/mob/living/silicon/proc/subsystem_crew_manifest() + set category = "Subystems" + set name = "Crew Manifest" + + crew_manifest.tgui_interact(usr) + /******************** * Crew Monitor * ********************/ diff --git a/code/modules/mob/logout.dm b/code/modules/mob/logout.dm index ffaeef3c09..d965956dfe 100644 --- a/code/modules/mob/logout.dm +++ b/code/modules/mob/logout.dm @@ -1,5 +1,4 @@ /mob/Logout() - SSnanoui.user_logout(src) // this is used to clean up (remove) this user's Nano UIs SStgui.on_logout(src) // Cleanup any TGUIs the user has open player_list -= src disconnect_time = world.realtime //VOREStation Addition: logging when we disappear. diff --git a/code/modules/modular_computers/file_system/program.dm b/code/modules/modular_computers/file_system/program.dm index 8bc12174bf..d5e55940d0 100644 --- a/code/modules/modular_computers/file_system/program.dm +++ b/code/modules/modular_computers/file_system/program.dm @@ -220,12 +220,6 @@ else return -1 -/obj/item/modular_computer/initial_data() - return get_header_data() - -/obj/item/modular_computer/update_layout() - return TRUE - /datum/computer_file/program/apply_visual(mob/M) if(TM) return TM.apply_visual(M) diff --git a/code/modules/nano/interaction/admin.dm b/code/modules/nano/interaction/admin.dm deleted file mode 100644 index dd4ce6ad17..0000000000 --- a/code/modules/nano/interaction/admin.dm +++ /dev/null @@ -1,7 +0,0 @@ -/* - This state checks that the user is an admin, end of story -*/ -/var/global/datum/topic_state/admin_state/admin_state = new() - -/datum/topic_state/admin_state/can_use_topic(var/src_object, var/mob/user) - return check_rights(R_ADMIN|R_EVENT, 0, user) ? STATUS_INTERACTIVE : STATUS_CLOSE diff --git a/code/modules/nano/interaction/base.dm b/code/modules/nano/interaction/base.dm deleted file mode 100644 index eb3e9ae5c1..0000000000 --- a/code/modules/nano/interaction/base.dm +++ /dev/null @@ -1,37 +0,0 @@ -/datum/proc/nano_host() - return src - -/datum/proc/nano_container() - return src - -/datum/proc/CanUseTopic(var/mob/user, var/datum/topic_state/state) - var/src_object = nano_host() - return state.can_use_topic(src_object, user) - -/datum/topic_state/proc/href_list(var/mob/user) - return list() - -/datum/topic_state/proc/can_use_topic(var/src_object, var/mob/user) - return STATUS_CLOSE - -/mob/proc/shared_nano_interaction() - if (src.stat || !client) - return STATUS_CLOSE // no updates, close the interface - else if (incapacitated()) - return STATUS_UPDATE // update only (orange visibility) - return STATUS_INTERACTIVE - -/mob/living/silicon/ai/shared_nano_interaction() - if(lacks_power()) - return STATUS_CLOSE - if (check_unable(1, 0)) - return STATUS_CLOSE - return ..() - -/mob/living/silicon/robot/shared_nano_interaction() - . = STATUS_INTERACTIVE - if(!has_power) - return STATUS_CLOSE - if(lockdown) - . = STATUS_DISABLED - return min(., ..()) diff --git a/code/modules/nano/interaction/conscious.dm b/code/modules/nano/interaction/conscious.dm deleted file mode 100644 index 143bc24956..0000000000 --- a/code/modules/nano/interaction/conscious.dm +++ /dev/null @@ -1,7 +0,0 @@ -/* - This state only checks if user is conscious. -*/ -/var/global/datum/topic_state/conscious_state/conscious_state = new() - -/datum/topic_state/conscious_state/can_use_topic(var/src_object, var/mob/user) - return user.stat == CONSCIOUS ? STATUS_INTERACTIVE : STATUS_CLOSE diff --git a/code/modules/nano/interaction/contained.dm b/code/modules/nano/interaction/contained.dm deleted file mode 100644 index 9ef595d020..0000000000 --- a/code/modules/nano/interaction/contained.dm +++ /dev/null @@ -1,18 +0,0 @@ -/* - This state checks if user is somewhere within src_object, as well as the default NanoUI interaction. -*/ -/var/global/datum/topic_state/contained_state/contained_state = new() - -/datum/topic_state/contained_state/can_use_topic(var/atom/src_object, var/mob/user) - if(!src_object.contains(user)) - return STATUS_CLOSE - - return user.shared_nano_interaction() - -/atom/proc/contains(var/atom/location) - if(!location) - return 0 - if(location == src) - return 1 - - return contains(location.loc) diff --git a/code/modules/nano/interaction/default.dm b/code/modules/nano/interaction/default.dm deleted file mode 100644 index dbb0781d33..0000000000 --- a/code/modules/nano/interaction/default.dm +++ /dev/null @@ -1,91 +0,0 @@ -/var/global/datum/topic_state/default/default_state = new() - -/datum/topic_state/default/href_list(var/mob/user) - return list() - -/datum/topic_state/default/can_use_topic(var/src_object, var/mob/user) - return user.default_can_use_topic(src_object) - -/mob/proc/default_can_use_topic(var/src_object) - return STATUS_CLOSE // By default no mob can do anything with NanoUI - -/mob/observer/dead/default_can_use_topic(var/src_object) - if(can_admin_interact()) - return STATUS_INTERACTIVE // Admins are more equal - if(!client || get_dist(src_object, src) > client.view) // Preventing ghosts from having a million windows open by limiting to objects in range - return STATUS_CLOSE - return STATUS_UPDATE // Ghosts can view updates - -/mob/living/silicon/pai/default_can_use_topic(var/src_object) - if((src_object == src || src_object == radio || src_object == communicator) && !stat) - return STATUS_INTERACTIVE - else - return ..() - -/mob/living/silicon/robot/default_can_use_topic(var/src_object) - . = shared_nano_interaction() - if(. <= STATUS_DISABLED) - return - - // robots can interact with things they can see within their view range - if((src_object in view(src)) && get_dist(src_object, src) <= src.client.view) - return STATUS_INTERACTIVE // interactive (green visibility) - return STATUS_DISABLED // no updates, completely disabled (red visibility) - -/mob/living/silicon/ai/default_can_use_topic(var/src_object) - . = shared_nano_interaction() - if(. != STATUS_INTERACTIVE) - return - - // Prevents the AI from using Topic on admin levels (by for example viewing through the court/thunderdome cameras) - // unless it's on the same level as the object it's interacting with. - var/turf/T = get_turf(src_object) - if(!T || !(z == T.z || (T.z in using_map.player_levels))) - return STATUS_CLOSE - - // If an object is in view then we can interact with it - if(src_object in view(client.view, src)) - return STATUS_INTERACTIVE - - // If we're installed in a chassi, rather than transfered to an inteliCard or other container, then check if we have camera view - if(is_in_chassis()) - //stop AIs from leaving windows open and using then after they lose vision - if(cameranet && !cameranet.checkTurfVis(get_turf(src_object))) - return STATUS_CLOSE - return STATUS_INTERACTIVE - else if(get_dist(src_object, src) <= client.view) // View does not return what one would expect while installed in an inteliCard - return STATUS_INTERACTIVE - - return STATUS_CLOSE - -//Some atoms such as vehicles might have special rules for how mobs inside them interact with NanoUI. -/atom/proc/contents_nano_distance(var/src_object, var/mob/living/user) - return user.shared_living_nano_distance(src_object) - -/mob/living/proc/shared_living_nano_distance(var/atom/movable/src_object) - if (!(src_object in view(4, src))) // If the src object is not in visable, disable updates - return STATUS_CLOSE - - var/dist = get_dist(src_object, src) - if (dist <= 1) - return STATUS_INTERACTIVE // interactive (green visibility) - else if (dist <= 2) - return STATUS_UPDATE // update only (orange visibility) - else if (dist <= 4) - return STATUS_DISABLED // no updates, completely disabled (red visibility) - return STATUS_CLOSE - -/mob/living/default_can_use_topic(var/src_object) - . = shared_nano_interaction(src_object) - if(. != STATUS_CLOSE) - if(loc) - . = min(., loc.contents_nano_distance(src_object, src)) - if(STATUS_INTERACTIVE) - return STATUS_UPDATE - -/mob/living/carbon/human/default_can_use_topic(var/src_object) - . = shared_nano_interaction(src_object) - if(. != STATUS_CLOSE) - . = min(., shared_living_nano_distance(src_object)) - if(. == STATUS_UPDATE && (TK in mutations)) // If we have telekinesis and remain close enough, allow interaction. - return STATUS_INTERACTIVE diff --git a/code/modules/nano/interaction/default_vr.dm b/code/modules/nano/interaction/default_vr.dm deleted file mode 100644 index 963963b3d7..0000000000 --- a/code/modules/nano/interaction/default_vr.dm +++ /dev/null @@ -1,6 +0,0 @@ -/mob/living/simple_mob/default_can_use_topic(var/src_object) - . = shared_nano_interaction(src_object) - if(. != STATUS_CLOSE) - . = min(., shared_living_nano_distance(src_object)) - -//Allows simple mobs to interact with nanoui as long as they have "has_hands = TRUE" \ No newline at end of file diff --git a/code/modules/nano/interaction/interactive.dm b/code/modules/nano/interaction/interactive.dm deleted file mode 100644 index ddd8f8f9e1..0000000000 --- a/code/modules/nano/interaction/interactive.dm +++ /dev/null @@ -1,7 +0,0 @@ -/* - This state always returns STATUS_INTERACTIVE -*/ -/var/global/datum/topic_state/interactive/interactive_state = new() - -/datum/topic_state/interactive/can_use_topic(var/src_object, var/mob/user) - return STATUS_INTERACTIVE diff --git a/code/modules/nano/interaction/inventory.dm b/code/modules/nano/interaction/inventory.dm deleted file mode 100644 index dd320f2bb2..0000000000 --- a/code/modules/nano/interaction/inventory.dm +++ /dev/null @@ -1,11 +0,0 @@ -/* - This state checks that the src_object is somewhere in the user's first-level inventory (in hands, on ear, etc.), but not further down (such as in bags). -*/ -/var/global/datum/topic_state/inventory_state/inventory_state = new() - -/datum/topic_state/inventory_state/can_use_topic(var/src_object, var/mob/user) - if(!(src_object in user)) - return STATUS_CLOSE - - - return user.shared_nano_interaction() diff --git a/code/modules/nano/interaction/inventory_deep.dm b/code/modules/nano/interaction/inventory_deep.dm deleted file mode 100644 index 9637c4df75..0000000000 --- a/code/modules/nano/interaction/inventory_deep.dm +++ /dev/null @@ -1,10 +0,0 @@ -/* - This state checks if src_object is contained anywhere in the user's inventory, including bags, etc. -*/ -/var/global/datum/topic_state/deep_inventory_state/deep_inventory_state = new() - -/datum/topic_state/deep_inventory_state/can_use_topic(var/src_object, var/mob/user) - if(!user.contains(src_object)) - return STATUS_CLOSE - - return user.shared_nano_interaction() diff --git a/code/modules/nano/interaction/inventory_vr.dm b/code/modules/nano/interaction/inventory_vr.dm deleted file mode 100644 index 21ee1ca590..0000000000 --- a/code/modules/nano/interaction/inventory_vr.dm +++ /dev/null @@ -1,32 +0,0 @@ -/* - This state checks that the src_object is on the user's glasses slot. -*/ -/var/global/datum/topic_state/glasses_state/glasses_state = new() - -/datum/topic_state/glasses_state/can_use_topic(var/src_object, var/mob/user) - if(ishuman(user)) - var/mob/living/carbon/human/H = user - if(H.glasses == src_object) - return user.shared_nano_interaction() - - return STATUS_CLOSE - -/var/global/datum/topic_state/nif_state/nif_state = new() - -/datum/topic_state/nif_state/can_use_topic(var/src_object, var/mob/user) - if(ishuman(user)) - var/mob/living/carbon/human/H = user - if(H.nif && H.nif.stat == NIF_WORKING && src_object == H.nif) - return user.shared_nano_interaction() - - return STATUS_CLOSE - -/var/global/datum/topic_state/commlink_state/commlink_state = new() - -/datum/topic_state/commlink_state/can_use_topic(var/src_object, var/mob/user) - if(ishuman(user)) - var/mob/living/carbon/human/H = user - if(H.nif && H.nif.stat == NIF_WORKING && H.nif.comm == src_object) - return user.shared_nano_interaction() - - return STATUS_CLOSE diff --git a/code/modules/nano/interaction/outside.dm b/code/modules/nano/interaction/outside.dm deleted file mode 100644 index 9ae0e24fe0..0000000000 --- a/code/modules/nano/interaction/outside.dm +++ /dev/null @@ -1,6 +0,0 @@ -/var/global/datum/topic_state/default/outside/outside_state = new() - -/datum/topic_state/default/outside/can_use_topic(var/src_object, var/mob/user) - if(user in src_object) - return STATUS_CLOSE - return ..() diff --git a/code/modules/nano/interaction/physical.dm b/code/modules/nano/interaction/physical.dm deleted file mode 100644 index 0571008481..0000000000 --- a/code/modules/nano/interaction/physical.dm +++ /dev/null @@ -1,18 +0,0 @@ -/var/global/datum/topic_state/physical/physical_state = new() - -/datum/topic_state/physical/can_use_topic(var/src_object, var/mob/user) - . = user.shared_nano_interaction(src_object) - if(. > STATUS_CLOSE) - return min(., user.check_physical_distance(src_object)) - -/mob/proc/check_physical_distance(var/src_object) - return STATUS_CLOSE - -/mob/observer/dead/check_physical_distance(var/src_object) - return default_can_use_topic(src_object) - -/mob/living/check_physical_distance(var/src_object) - return shared_living_nano_distance(src_object) - -/mob/living/silicon/check_physical_distance(var/src_object) - return max(STATUS_UPDATE, shared_living_nano_distance(src_object)) diff --git a/code/modules/nano/interaction/remote.dm b/code/modules/nano/interaction/remote.dm deleted file mode 100644 index 8e6ded6c84..0000000000 --- a/code/modules/nano/interaction/remote.dm +++ /dev/null @@ -1,39 +0,0 @@ -/* - This state checks that user is capable, within range of the remoter, etc. and that src_object meets the basic requirements for interaction (being powered, non-broken, etc. - Whoever initializes this state is also responsible for deleting it properly. -*/ -/datum/topic_state/remote - var/datum/remoter - var/datum/remote_target - var/datum/topic_state/remoter_state - -/datum/topic_state/remote/New(var/remoter, var/remote_target, var/datum/topic_state/remoter_state = default_state) - src.remoter = remoter - src.remote_target = remote_target - src.remoter_state = remoter_state - ..() - -/datum/topic_state/remote/Destroy() - src.remoter = null - src.remoter_state = null - - // Force an UI update before we go, ensuring that any windows we may have opened for the remote target closes. - SSnanoui.update_uis(remote_target.nano_container()) - remote_target = null - return ..() - -/datum/topic_state/remote/can_use_topic(var/datum/src_object, var/mob/user) - if(!(remoter && remoter_state)) // The remoter is gone, let us leave - return STATUS_CLOSE - - if(src_object != remote_target) - error("remote - Unexpected src_object: Expected '[remote_target]'/[remote_target.type], was '[src_object]'/[src_object.type]") - - // This checks if src_object is powered, etc. - // The interactive state is otherwise simplistic and only returns STATUS_INTERACTIVE and never checks distances, etc. - . = src_object.CanUseTopic(user, interactive_state) - if(. == STATUS_CLOSE) - return - - // This is the (generally) heavy checking, making sure the user is capable, within range of the remoter source, etc. - return min(., remoter.CanUseTopic(user, remoter_state)) diff --git a/code/modules/nano/interaction/self.dm b/code/modules/nano/interaction/self.dm deleted file mode 100644 index 639e50e161..0000000000 --- a/code/modules/nano/interaction/self.dm +++ /dev/null @@ -1,9 +0,0 @@ -/* - This state checks that the src_object is the same the as user -*/ -/var/global/datum/topic_state/self_state/self_state = new() - -/datum/topic_state/self_state/can_use_topic(var/src_object, var/mob/user) - if(src_object != user) - return STATUS_CLOSE - return user.shared_nano_interaction() diff --git a/code/modules/nano/interaction/zlevel.dm b/code/modules/nano/interaction/zlevel.dm deleted file mode 100644 index 80d4c2e601..0000000000 --- a/code/modules/nano/interaction/zlevel.dm +++ /dev/null @@ -1,13 +0,0 @@ -/* - This state checks that the user is on the same Z-level as src_object -*/ - -/var/global/datum/topic_state/z_state/z_state = new() - -/datum/topic_state/z_state/can_use_topic(var/src_object, var/mob/user) - var/turf/turf_obj = get_turf(src_object) - var/turf/turf_usr = get_turf(user) - if(!turf_obj || !turf_usr) - return STATUS_CLOSE - - return turf_obj.z == turf_usr.z ? STATUS_INTERACTIVE : STATUS_CLOSE diff --git a/code/modules/nano/modules/nano_module.dm b/code/modules/nano/modules/nano_module.dm deleted file mode 100644 index 87199e79dc..0000000000 --- a/code/modules/nano/modules/nano_module.dm +++ /dev/null @@ -1,60 +0,0 @@ -/datum/nano_module - var/name - var/datum/host - var/list/using_access - -/datum/nano_module/New(var/datum/host) - ..() - src.host = host.nano_host() - -/datum/nano_module/nano_host() - return host ? host : src - -/datum/nano_module/proc/can_still_topic(var/datum/topic_state/state = default_state) - return CanUseTopic(usr, state) == STATUS_INTERACTIVE - -/datum/nano_module/proc/check_eye(var/mob/user) - return -1 - -/datum/nano_module/proc/check_access(var/mob/user, var/access) - if(!access) - return 1 - - if(using_access) - if(access in using_access) - return 1 - else - return 0 - - if(!istype(user)) - return 0 - - var/obj/item/weapon/card/id/I = user.GetIdCard() - if(!I) - return 0 - - if(access in I.access) - return 1 - - return 0 - -/datum/nano_module/proc/print_text(var/text, var/mob/user) - var/obj/item/modular_computer/MC = nano_host() - if(istype(MC)) - if(!MC.nano_printer) - to_chat(user, "Error: No printer detected. Unable to print document.") - return - - if(!MC.nano_printer.print_text(text)) - to_chat(user, "Error: Printer was unable to print the document. It may be out of paper.") - else - to_chat(user, "Error: Unable to detect compatible printer interface. Are you running NTOSv2 compatible system?") - -/datum/proc/initial_data() - return list() - -/datum/proc/update_layout() - return FALSE - -/datum/nano_module/proc/relaymove(var/mob/user, direction) - return FALSE diff --git a/code/modules/nano/nanoexternal.dm b/code/modules/nano/nanoexternal.dm deleted file mode 100644 index 08f9deffa9..0000000000 --- a/code/modules/nano/nanoexternal.dm +++ /dev/null @@ -1,44 +0,0 @@ - // This file contains all Nano procs/definitions for external classes/objects - - /** - * Called when a Nano UI window is closed - * This is how Nano handles closed windows - * It must be a verb so that it can be called using winset - * - * @return nothing - */ -/client/verb/nanoclose(var/uiref as text) - set hidden = 1 // hide this verb from the user's panel - set name = "nanoclose" - - var/datum/nanoui/ui = locate(uiref) - - if (istype(ui)) - ui.close() - - if(ui.ref) - var/href = "close=1" - src.Topic(href, params2list(href), ui.ref) // this will direct to the atom's Topic() proc via client.Topic() - else if (ui.on_close_logic) - // no atomref specified (or not found) - // so just reset the user mob's machine var - if(src && src.mob) - src.mob.unset_machine() - - /** - * The ui_interact proc is used to open and update Nano UIs - * If ui_interact is not used then the UI will not update correctly - * ui_interact is currently defined for /atom/movable - * - * @param user /mob The mob who is interacting with this ui - * @param ui_key string A string key to use for this ui. Allows for multiple unique uis on one obj/mob (defaut value "main") - * @param ui /datum/nanoui This parameter is passed by the nanoui process() proc when updating an open ui - * @param force_open boolean Force the UI to (re)open, even if it's already open - * - * @return nothing - */ -/datum/proc/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/nano_ui/master_ui = null, var/datum/topic_state/state = default_state) - return - -// Used by the Nano UI Manager (/datum/nanomanager) to track UIs opened by this mob -/mob/var/list/open_uis = list() diff --git a/code/modules/nano/nanomanager.dm b/code/modules/nano/nanomanager.dm deleted file mode 100644 index 69b0e7b77e..0000000000 --- a/code/modules/nano/nanomanager.dm +++ /dev/null @@ -1,224 +0,0 @@ - - /** - * Get an open /nanoui ui for the current user, src_object and ui_key and try to update it with data - * - * @param user /mob The mob who opened/owns the ui - * @param src_object /obj|/mob The obj or mob which the ui belongs to - * @param ui_key string A string key used for the ui - * @param ui /datum/nanoui An existing instance of the ui (can be null) - * @param data list The data to be passed to the ui, if it exists - * @param force_open boolean The ui is being forced to (re)open, so close ui if it exists (instead of updating) - * - * @return /nanoui Returns the found ui, for null if none exists - */ -/datum/controller/subsystem/nanoui/proc/try_update_ui(var/mob/user, src_object, ui_key, var/datum/nanoui/ui, data, var/force_open = 0) - if (isnull(ui)) // no ui has been passed, so we'll search for one - { - ui = get_open_ui(user, src_object, ui_key) - } - if (!isnull(ui)) - // The UI is already open - if (!force_open) - ui.push_data(data) - return ui - else - ui.reinitialise(new_initial_data=data) - return ui - - return null - - /** - * Get an open /nanoui ui for the current user, src_object and ui_key - * - * @param user /mob The mob who opened/owns the ui - * @param src_object /obj|/mob The obj or mob which the ui belongs to - * @param ui_key string A string key used for the ui - * - * @return /nanoui Returns the found ui, or null if none exists - */ -/datum/controller/subsystem/nanoui/proc/get_open_ui(var/mob/user, src_object, ui_key) - var/src_object_key = "\ref[src_object]" - if (isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list)) - //testing("nanomanager/get_open_ui mob [user.name] [src_object:name] [ui_key] - there are no uis open") - return null - else if (isnull(open_uis[src_object_key][ui_key]) || !istype(open_uis[src_object_key][ui_key], /list)) - //testing("nanomanager/get_open_ui mob [user.name] [src_object:name] [ui_key] - there are no uis open for this object") - return null - - for (var/datum/nanoui/ui in open_uis[src_object_key][ui_key]) - if (ui.user == user) - return ui - - //testing("nanomanager/get_open_ui mob [user.name] [src_object:name] [ui_key] - ui not found") - return null - - /** - * Update all /nanoui uis attached to src_object - * - * @param src_object /obj|/mob The obj or mob which the uis are attached to - * - * @return int The number of uis updated - */ -/datum/controller/subsystem/nanoui/proc/update_uis(src_object) - var/src_object_key = "\ref[src_object]" - if (isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list)) - return 0 - - var/update_count = 0 - for (var/ui_key in open_uis[src_object_key]) - for (var/datum/nanoui/ui in open_uis[src_object_key][ui_key]) - if(ui && ui.src_object && ui.user && ui.src_object.nano_host()) - ui.process(1) - update_count++ - return update_count - - /** - * Close all /nanoui uis attached to src_object - * - * @param src_object /obj|/mob The obj or mob which the uis are attached to - * - * @return int The number of uis close - */ -/datum/controller/subsystem/nanoui/proc/close_uis(src_object) - var/src_object_key = "\ref[src_object]" - if (isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list)) - return 0 - - var/close_count = 0 - for (var/ui_key in open_uis[src_object_key]) - for (var/datum/nanoui/ui in open_uis[src_object_key][ui_key]) - if(ui && ui.src_object && ui.user && ui.src_object.nano_host()) - ui.close() - close_count++ - return close_count - - /** - * Update /nanoui uis belonging to user - * - * @param user /mob The mob who owns the uis - * @param src_object /obj|/mob If src_object is provided, only update uis which are attached to src_object (optional) - * @param ui_key string If ui_key is provided, only update uis with a matching ui_key (optional) - * - * @return int The number of uis updated - */ -/datum/controller/subsystem/nanoui/proc/update_user_uis(var/mob/user, src_object = null, ui_key = null) - if (isnull(user.open_uis) || !istype(user.open_uis, /list) || open_uis.len == 0) - return 0 // has no open uis - - var/update_count = 0 - for (var/datum/nanoui/ui in user.open_uis) - if ((isnull(src_object) || !isnull(src_object) && ui.src_object == src_object) && (isnull(ui_key) || !isnull(ui_key) && ui.ui_key == ui_key)) - ui.process(1) - update_count++ - - return update_count - - /** - * Close /nanoui uis belonging to user - * - * @param user /mob The mob who owns the uis - * @param src_object /obj|/mob If src_object is provided, only close uis which are attached to src_object (optional) - * @param ui_key string If ui_key is provided, only close uis with a matching ui_key (optional) - * - * @return int The number of uis closed - */ -/datum/controller/subsystem/nanoui/proc/close_user_uis(var/mob/user, src_object = null, ui_key = null) - if (isnull(user.open_uis) || !istype(user.open_uis, /list) || open_uis.len == 0) - //testing("nanomanager/close_user_uis mob [user.name] has no open uis") - return 0 // has no open uis - - var/close_count = 0 - for (var/datum/nanoui/ui in user.open_uis) - if ((isnull(src_object) || !isnull(src_object) && ui.src_object == src_object) && (isnull(ui_key) || !isnull(ui_key) && ui.ui_key == ui_key)) - ui.close() - close_count++ - - //testing("nanomanager/close_user_uis mob [user.name] closed [open_uis.len] of [close_count] uis") - - return close_count - - /** - * Add a /nanoui ui to the list of open uis - * This is called by the /nanoui open() proc - * - * @param ui /nanoui The ui to add - * - * @return nothing - */ -/datum/controller/subsystem/nanoui/proc/ui_opened(var/datum/nanoui/ui) - var/src_object_key = "\ref[ui.src_object]" - if (isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list)) - open_uis[src_object_key] = list(ui.ui_key = list()) - else if (isnull(open_uis[src_object_key][ui.ui_key]) || !istype(open_uis[src_object_key][ui.ui_key], /list)) - open_uis[src_object_key][ui.ui_key] = list(); - - ui.user.open_uis |= ui - var/list/uis = open_uis[src_object_key][ui.ui_key] - uis |= ui - processing_uis |= ui - //testing("nanomanager/ui_opened mob [ui.user.name] [ui.src_object:name] [ui.ui_key] - user.open_uis [ui.user.open_uis.len] | uis [uis.len] | processing_uis [processing_uis.len]") - - /** - * Remove a /nanoui ui from the list of open uis - * This is called by the /nanoui close() proc - * - * @param ui /nanoui The ui to remove - * - * @return int 0 if no ui was removed, 1 if removed successfully - */ -/datum/controller/subsystem/nanoui/proc/ui_closed(var/datum/nanoui/ui) - var/src_object_key = "\ref[ui.src_object]" - if (isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list)) - return 0 // wasn't open - else if (isnull(open_uis[src_object_key][ui.ui_key]) || !istype(open_uis[src_object_key][ui.ui_key], /list)) - return 0 // wasn't open - - processing_uis.Remove(ui) - if(ui.user) // Sanity check in case a user has been deleted (say a blown up borg watching the alarm interface) - ui.user.open_uis.Remove(ui) - var/list/uis = open_uis[src_object_key][ui.ui_key] - uis.Remove(ui) - - //testing("nanomanager/ui_closed mob [ui.user.name] [ui.src_object:name] [ui.ui_key] - user.open_uis [ui.user.open_uis.len] | uis [uis.len] | processing_uis [processing_uis.len]") - - return 1 - - /** - * This is called on user logout - * Closes/clears all uis attached to the user's /mob - * - * @param user /mob The user's mob - * - * @return nothing - */ - -// -/datum/controller/subsystem/nanoui/proc/user_logout(var/mob/user) - //testing("nanomanager/user_logout user [user.name]") - return close_user_uis(user) - - /** - * This is called when a player transfers from one mob to another - * Transfers all open UIs to the new mob - * - * @param oldMob /mob The user's old mob - * @param newMob /mob The user's new mob - * - * @return nothing - */ -/datum/controller/subsystem/nanoui/proc/user_transferred(var/mob/oldMob, var/mob/newMob) - //testing("nanomanager/user_transferred from mob [oldMob.name] to mob [newMob.name]") - if (!oldMob || isnull(oldMob.open_uis) || !istype(oldMob.open_uis, /list) || open_uis.len == 0) - //testing("nanomanager/user_transferred mob [oldMob.name] has no open uis") - return 0 // has no open uis - - if (isnull(newMob.open_uis) || !istype(newMob.open_uis, /list)) - newMob.open_uis = list() - - for (var/datum/nanoui/ui in oldMob.open_uis) - ui.user = newMob - newMob.open_uis.Add(ui) - - oldMob.open_uis.Cut() - - return 1 // success \ No newline at end of file diff --git a/code/modules/nano/nanoui.dm b/code/modules/nano/nanoui.dm deleted file mode 100644 index 29863f5617..0000000000 --- a/code/modules/nano/nanoui.dm +++ /dev/null @@ -1,529 +0,0 @@ -/********************************************************** -NANO UI FRAMEWORK - -nanoui class (or whatever Byond calls classes) - -nanoui is used to open and update nano browser uis -**********************************************************/ - -/datum/nanoui - // the user who opened this ui - var/mob/user - // the object this ui "belongs" to - var/datum/src_object - // the title of this ui - var/title - // the key of this ui, this is to allow multiple (different) uis for each src_object - var/ui_key - // window_id is used as the window name/identifier for browse and onclose - var/window_id - // the browser window width - var/width = 0 - // the browser window height - var/height = 0 - // whether to use extra logic when window closes - var/on_close_logic = 1 - // an extra ref to use when the window is closed, usually null - var/atom/ref = null - // options for modifying window behaviour - var/window_options = "focus=0;can_close=1;can_minimize=1;can_maximize=0;can_resize=1;titlebar=1;" // window option is set using window_id - // the list of stylesheets to apply to this ui - var/list/stylesheets = list() - // the list of javascript scripts to use for this ui - var/list/scripts = list() - // a list of templates which can be used with this ui - var/templates[0] - // the layout key for this ui (this is used on the frontend, leave it as "default" unless you know what you're doing) - var/layout_key = "default" - // this sets whether to re-render the ui layout with each update (default 0, turning on will break the map ui if it's in use) - var/auto_update_layout = 0 - // this sets whether to re-render the ui content with each update (default 1) - var/auto_update_content = 1 - // the default state to use for this ui (this is used on the frontend, leave it as "default" unless you know what you're doing) - var/state_key = "default" - // show the map ui, this is used by the default layout - var/show_map = 0 - // the map z level to display - var/map_z_level = 1 - // initial data, containing the full data structure, must be sent to the ui (the data structure cannot be extended later on) - var/list/initial_data[0] - // set to 1 to update the ui automatically every master_controller tick - var/is_auto_updating = 0 - // the current status/visibility of the ui - var/status = STATUS_INTERACTIVE - - // Relationship between a master interface and its children. Used in update_status - var/datum/nanoui/master_ui - var/list/datum/nanoui/children = list() - var/datum/topic_state/state = null - - /** - * Create a new nanoui instance. - * - * @param nuser /mob The mob who has opened/owns this ui - * @param nsrc_object /obj|/mob The obj or mob which this ui belongs to - * @param nui_key string A string key to use for this ui. Allows for multiple unique uis on one src_oject - * @param ntemplate string The filename of the template file from /nano/templates (e.g. "my_template.tmpl") - * @param ntitle string The title of this ui - * @param nwidth int the width of the ui window - * @param nheight int the height of the ui window - * @param nref /atom A custom ref to use if "on_close_logic" is set to 1 - * - * @return /nanoui new nanoui object - */ -/datum/nanoui/New(nuser, nsrc_object, nui_key, ntemplate_filename, ntitle = 0, nwidth = 0, nheight = 0, var/atom/nref = null, var/datum/nanoui/master_ui = null, var/datum/topic_state/state = default_state) - user = nuser - src_object = nsrc_object - ui_key = nui_key - window_id = "[ui_key]\ref[src_object]" - - src.master_ui = master_ui - if(master_ui) - master_ui.children += src - src.state = state - - // add the passed template filename as the "main" template, this is required - add_template("main", ntemplate_filename) - - if (ntitle) - title = sanitize(ntitle) - if (nwidth) - width = nwidth - if (nheight) - height = nheight - if (nref) - ref = nref - - add_common_assets() - - /** - * Use this proc to add assets which are common to (and required by) all nano uis - * - * @return nothing - */ -/datum/nanoui/proc/add_common_assets() - add_script("libraries.min.js") // A JS file comprising of jQuery, doT.js and jQuery Timer libraries (compressed together) - add_script("nano_utility.js") // The NanoUtility JS, this is used to store utility functions. - add_script("nano_templates_bundle.js") // Contains all templates, generated by asset cache system at server start. - add_script("nano_template.js") // The NanoTemplate JS, this is used to render templates. - add_script("nano_state_manager.js") // The NanoStateManager JS, it handles updates from the server and passes data to the current state - add_script("nano_state.js") // The NanoState JS, this is the base state which all states must inherit from - add_script("nano_state_default.js") // The NanoStateDefault JS, this is the "default" state (used by all UIs by default), which inherits from NanoState - add_script("nano_state_pda.js") // The NanoStatePDA JS, this is the state used for PDAs. - add_script("nano_base_callbacks.js") // The NanoBaseCallbacks JS, this is used to set up (before and after update) callbacks which are common to all UIs - add_script("nano_base_helpers.js") // The NanoBaseHelpers JS, this is used to set up template helpers which are common to all UIs - add_stylesheet("shared.css") // this CSS sheet is common to all UIs - add_stylesheet("shared_vr.css") // VOREStation Add - add_stylesheet("icons.css") // this CSS sheet is common to all UIs - - /** - * Set the current status (also known as visibility) of this ui. - * - * @param state int The status to set, see the defines at the top of this file - * @param push_update int (bool) Push an update to the ui to update it's status (an update is always sent if the status has changed to red (0)) - * - * @return nothing - */ -/datum/nanoui/proc/set_status(state, push_update) - if (state != status) // Only update if it is different - if (status == STATUS_DISABLED) - status = state - if (push_update) - update() - else - status = state - if (push_update || status == 0) - push_data(null, 1) // Update the UI, force the update in case the status is 0, data is null so that previous data is used - - /** - * Update the status (visibility) of this ui based on the user's status - * - * @param push_update int (bool) Push an update to the ui to update it's status. This is set to 0/false if an update is going to be pushed anyway (to avoid unnessary updates) - * - * @return nothing - */ -/datum/nanoui/proc/update_status(var/push_update = 0) - var/obj/host = src_object.nano_host() - var/new_status = host.CanUseTopic(user, state) - if(master_ui) - new_status = min(new_status, master_ui.status) - - set_status(new_status, push_update) - if(new_status == STATUS_CLOSE) - close() - - /** - * Set the ui to auto update (every master_controller tick) - * - * @param state int (bool) Set auto update to 1 or 0 (true/false) - * - * @return nothing - */ -/datum/nanoui/proc/set_auto_update(nstate = 1) - is_auto_updating = nstate - - /** - * Set the initial data for the ui. This is vital as the data structure set here cannot be changed when pushing new updates. - * - * @param data /list The list of data for this ui - * - * @return nothing - */ -/datum/nanoui/proc/set_initial_data(list/data) - initial_data = data - - /** - * Get config data to sent to the ui. - * - * @return /list config data - */ -/datum/nanoui/proc/get_config_data() - var/name = "[src_object]" - name = sanitize(name) - var/list/config_data = list( - "title" = title, - "srcObject" = list("name" = name), - "stateKey" = state_key, - "status" = status, - "autoUpdateLayout" = auto_update_layout, - "autoUpdateContent" = auto_update_content, - "showMap" = show_map, - "mapZLevel" = map_z_level, - "user" = list("name" = user.name) - ) - return config_data - - /** - * Get data to sent to the ui. - * - * @param data /list The list of general data for this ui (can be null to use previous data sent) - * - * @return /list data to send to the ui - */ -/datum/nanoui/proc/get_send_data(var/list/data) - var/list/config_data = get_config_data() - - var/list/send_data = list("config" = config_data) - - if (!isnull(data)) - send_data["data"] = data - - return send_data - - /** - * Set the browser window options for this ui - * - * @param nwindow_options string The new window options - * - * @return nothing - */ -/datum/nanoui/proc/set_window_options(nwindow_options) - window_options = nwindow_options - - /** - * Add a CSS stylesheet to this UI - * These must be added before the UI has been opened, adding after that will have no effect - * - * @param file string The name of the CSS file from /nano/css (e.g. "my_style.css") - * - * @return nothing - */ -/datum/nanoui/proc/add_stylesheet(file) - stylesheets.Add(file) - - /** - * Add a JavsScript script to this UI - * These must be added before the UI has been opened, adding after that will have no effect - * - * @param file string The name of the JavaScript file from /nano/js (e.g. "my_script.js") - * - * @return nothing - */ -/datum/nanoui/proc/add_script(file) - scripts.Add(file) - - /** - * Add a template for this UI - * Templates are combined with the data sent to the UI to create the rendered view - * These must be added before the UI has been opened, adding after that will have no effect - * - * @param key string The key which is used to reference this template in the frontend - * @param filename string The name of the template file from /nano/templates (e.g. "my_template.tmpl") - * - * @return nothing - */ -/datum/nanoui/proc/add_template(key, filename) - templates[key] = filename - - /** - * Set the layout key for use in the frontend Javascript - * The layout key is the basic layout key for the page - * Two files are loaded on the client based on the layout key varable: - * -> a template in /nano/templates with the filename "layout_.tmpl - * -> a CSS stylesheet in /nano/css with the filename "layout_.css - * - * @param nlayout string The layout key to use - * - * @return nothing - */ -/datum/nanoui/proc/set_layout_key(nlayout_key) - layout_key = lowertext(nlayout_key) - - /** - * Set the ui to update the layout (re-render it) on each update, turning this on will break the map ui (if it's being used) - * - * @param state int (bool) Set update to 1 or 0 (true/false) (default 0) - * - * @return nothing - */ -/datum/nanoui/proc/set_auto_update_layout(nstate) - auto_update_layout = nstate - - /** - * Set the ui to update the main content (re-render it) on each update - * - * @param state int (bool) Set update to 1 or 0 (true/false) (default 1) - * - * @return nothing - */ -/datum/nanoui/proc/set_auto_update_content(nstate) - auto_update_content = nstate - - /** - * Set the state key for use in the frontend Javascript - * - * @param nstate_key string The key of the state to use - * - * @return nothing - */ -/datum/nanoui/proc/set_state_key(nstate_key) - state_key = nstate_key - - /** - * Toggle showing the map ui - * - * @param nstate_key boolean 1 to show map, 0 to hide (default is 0) - * - * @return nothing - */ -/datum/nanoui/proc/set_show_map(nstate) - show_map = nstate - - /** - * Toggle showing the map ui - * - * @param nstate_key boolean 1 to show map, 0 to hide (default is 0) - * - * @return nothing - */ -/datum/nanoui/proc/set_map_z_level(nz) - map_z_level = nz - - /** - * Set whether or not to use the "old" on close logic (mainly unset_machine()) - * - * @param state int (bool) Set on_close_logic to 1 or 0 (true/false) - * - * @return nothing - */ -/datum/nanoui/proc/use_on_close_logic(state) - on_close_logic = state - - /** - * Return the HTML for this UI - * - * @return string HTML for the UI - */ -/datum/nanoui/proc/get_html() - - // before the UI opens, add the layout files based on the layout key - add_stylesheet("layout_[layout_key].css") - add_template("layout", "layout_[layout_key].tmpl") - - var/head_content = "" - - for (var/filename in scripts) - head_content += " " - - for (var/filename in stylesheets) - head_content += " " - - var/template_data_json = "{}" // An empty JSON object - if (templates.len > 0) - template_data_json = strip_improper(json_encode(templates)) - - var/list/send_data = get_send_data(initial_data) - var/initial_data_json = replacetext(replacetext(json_encode(send_data), """, "&#34;"), "'", "'") - initial_data_json = strip_improper(initial_data_json); - - var/url_parameters_json = json_encode(list("src" = "\ref[src]")) - - return {" - - - - - - - [head_content] - - -
-
- - - - "} - - /** - * Open this UI - * - * @return nothing - */ -/datum/nanoui/proc/open() - if(!user.client) - return - - // An attempted fix to UIs sometimes locking up spamming runtime errors due to src_object being null for whatever reason. - // This hard-deletes the UI, preventing the device that uses the UI from being locked up permanently. - if(!src_object) - del(src) - - var/window_size = "" - if (width && height) - window_size = "size=[width]x[height];" - update_status(0) - if(status == STATUS_CLOSE) - return - - user << browse(get_html(), "window=[window_id];[window_size][window_options]") - winset(user, "mapwindow.map", "focus=true") // return keyboard focus to map - on_close_winset() - //onclose(user, window_id) - SSnanoui.ui_opened(src) - - /** - * Reinitialise this UI, potentially with a different template and/or initial data - * - * @return nothing - */ -/datum/nanoui/proc/reinitialise(template, new_initial_data) - if(template) - add_template("main", template) - if(new_initial_data) - set_initial_data(new_initial_data) - open() - - /** - * Close this UI - * - * @return nothing - */ -/datum/nanoui/proc/close() - is_auto_updating = 0 - SSnanoui.ui_closed(src) - user << browse(null, "window=[window_id]") - for(var/datum/nanoui/child in children) - child.close() - children.Cut() - state = null - master_ui = null - - /** - * Set the UI window to call the nanoclose verb when the window is closed - * This allows Nano to handle closed windows - * - * @return nothing - */ -/datum/nanoui/proc/on_close_winset() - if(!user.client) - return - var/params = "\ref[src]" - - winset(user, window_id, "on-close=\"nanoclose [params]\"") - - /** - * Push data to an already open UI window - * - * @return nothing - */ -/datum/nanoui/proc/push_data(data, force_push = 0) - update_status(0) - if (status == STATUS_DISABLED && !force_push) - return // Cannot update UI, no visibility - - var/list/send_data = get_send_data(data) - - //to_chat(user,list2json_usecache(send_data)) // used for debugging //NANO DEBUG HOOK - user << output(list2params(list(strip_improper(json_encode(send_data)))),"[window_id].browser:receiveUpdateData") - - /** - * This Topic() proc is called whenever a user clicks on a link within a Nano UI - * If the UI status is currently STATUS_INTERACTIVE then call the src_object Topic() - * If the src_object Topic() returns 1 (true) then update all UIs attached to src_object - * - * @return nothing - */ -/datum/nanoui/Topic(href, href_list) - update_status(0) // update the status - if (status != STATUS_INTERACTIVE || user != usr) // If UI is not interactive or usr calling Topic is not the UI user - return - - // This is used to toggle the nano map ui - var/map_update = 0 - if(href_list["showMap"]) - set_show_map(text2num(href_list["showMap"])) - map_update = 1 - - if(href_list["mapZLevel"]) - set_map_z_level(text2num(href_list["mapZLevel"])) - map_update = 1 - - if ((src_object && src_object.Topic(href, href_list, state)) || map_update) - SSnanoui.update_uis(src_object) // update all UIs attached to src_object - - /** - * Process this UI, updating the entire UI or just the status (aka visibility) - * This process proc is called by the master_controller - * - * @param update string For this UI to update - * - * @return nothing - */ -/datum/nanoui/process(update = 0) - if (!src_object || !user) - close() - return - - if (status && (update || is_auto_updating)) - update() // Update the UI (update_status() is called whenever a UI is updated) - else - update_status(1) // Not updating UI, so lets check here if status has changed - - /** - * Update the UI - * - * @return nothing - */ -/datum/nanoui/proc/update(var/force_open = 0) - src_object.ui_interact(user, ui_key, src, force_open, master_ui, state) diff --git a/code/modules/overmap/ships/computers/shuttle.dm b/code/modules/overmap/ships/computers/shuttle.dm index f51587d594..76c0d3e6d1 100644 --- a/code/modules/overmap/ships/computers/shuttle.dm +++ b/code/modules/overmap/ships/computers/shuttle.dm @@ -47,6 +47,6 @@ else to_chat(usr,"No valid landing sites in range.") possible_d = shuttle.get_possible_destinations() - if(CanInteract(usr, global.default_state) && (D in possible_d)) + if(CanInteract(usr, GLOB.tgui_default_state) && (D in possible_d)) shuttle.set_destination(possible_d[D]) return TRUE diff --git a/code/modules/paperwork/faxmachine.dm b/code/modules/paperwork/faxmachine.dm index 269c0fc995..9f4a183b31 100644 --- a/code/modules/paperwork/faxmachine.dm +++ b/code/modules/paperwork/faxmachine.dm @@ -17,8 +17,10 @@ var/list/adminfaxes = list() //cache for faxes that have been sent to admins active_power_usage = 200 circuit = /obj/item/weapon/circuitboard/fax - var/obj/item/weapon/card/id/scan = null // identification - var/authenticated = 0 + var/obj/item/weapon/card/id/scan = null + var/authenticated = null + var/rank = null + var/sendcooldown = 0 // to avoid spamming fax messages var/department = "Unknown" // our department var/destination = null // the department we're sending to @@ -33,91 +35,101 @@ var/list/adminfaxes = list() //cache for faxes that have been sent to admins /obj/machinery/photocopier/faxmachine/attack_hand(mob/user as mob) user.set_machine(src) - ui_interact(user) + tgui_interact(user) -/** - * Display the NanoUI window for the fax machine. - * - * See NanoUI documentation for details. - */ -/obj/machinery/photocopier/faxmachine/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - user.set_machine(src) +/obj/machinery/photocopier/faxmachine/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "Fax", name) + ui.open() - var/list/data = list() - if(scan) - data["scanName"] = scan.name - else - data["scanName"] = null - data["bossName"] = using_map.boss_name +/obj/machinery/photocopier/faxmachine/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state) + var/list/data = ..() + data["scan"] = scan ? scan.name : null data["authenticated"] = authenticated + data["rank"] = rank + data["isAI"] = isAI(user) + data["isRobot"] = isrobot(user) + + data["bossName"] = using_map.boss_name data["copyItem"] = copyitem - if(copyitem) - data["copyItemName"] = copyitem.name - else - data["copyItemName"] = null data["cooldown"] = sendcooldown data["destination"] = destination - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - ui = new(user, src, ui_key, "fax.tmpl", src.name, 500, 500) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(10) //this machine is so unimportant let's not have it update that often. + return data -/obj/machinery/photocopier/faxmachine/Topic(href, href_list) - if(href_list["send"]) - if(copyitem) - if (destination in admin_departments) - send_admin_fax(usr, destination) - else - sendfax(destination) +/obj/machinery/photocopier/faxmachine/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) + if(..()) + return TRUE - if (sendcooldown) - spawn(sendcooldown) // cooldown time - sendcooldown = 0 - - else if(href_list["remove"]) - if(copyitem) - if(get_dist(usr, src) >= 2) - to_chat(usr, "\The [copyitem] is too far away for you to remove it.") - return - copyitem.loc = usr.loc - usr.put_in_hands(copyitem) - to_chat(usr, "You take \the [copyitem] out of \the [src].") - copyitem = null - - if(href_list["scan"]) - if (scan) - if(ishuman(usr)) - scan.loc = usr.loc - if(!usr.get_active_hand()) + switch(action) + if("scan") + if(scan) + scan.forceMove(loc) + if(ishuman(usr) && !usr.get_active_hand()) usr.put_in_hands(scan) scan = null else - scan.loc = src.loc + var/obj/item/I = usr.get_active_hand() + if(istype(I, /obj/item/weapon/card/id)) + usr.drop_item() + I.forceMove(src) + scan = I + return TRUE + if("login") + var/login_type = text2num(params["login_type"]) + if(login_type == LOGIN_TYPE_NORMAL && istype(scan)) + if(check_access(scan)) + authenticated = scan.registered_name + rank = scan.assignment + else if(login_type == LOGIN_TYPE_AI && isAI(usr)) + authenticated = usr.name + rank = "AI" + else if(login_type == LOGIN_TYPE_ROBOT && isrobot(usr)) + authenticated = usr.name + var/mob/living/silicon/robot/R = usr + rank = "[R.modtype] [R.braintype]" + return TRUE + if("logout") + if(scan) + scan.forceMove(loc) + if(ishuman(usr) && !usr.get_active_hand()) + usr.put_in_hands(scan) scan = null - else - var/obj/item/I = usr.get_active_hand() - if (istype(I, /obj/item/weapon/card/id) && usr.unEquip(I)) - I.loc = src - scan = I - authenticated = 0 + authenticated = null + return TRUE + if("remove") + if(copyitem) + if(get_dist(usr, src) >= 2) + to_chat(usr, "\The [copyitem] is too far away for you to remove it.") + return + copyitem.forceMove(loc) + usr.put_in_hands(copyitem) + to_chat(usr, "You take \the [copyitem] out of \the [src].") + copyitem = null - if(href_list["dept"]) - var/lastdestination = destination - destination = input(usr, "Which department?", "Choose a department", "") as null|anything in (alldepartments + admin_departments) - if(!destination) destination = lastdestination + if(!authenticated) + return + + switch(action) + if("send") + if(copyitem) + if (destination in admin_departments) + send_admin_fax(usr, destination) + else + sendfax(destination) - if(href_list["auth"]) - if ( (!( authenticated ) && (scan)) ) - if (check_access(scan)) - authenticated = 1 + if (sendcooldown) + spawn(sendcooldown) // cooldown time + sendcooldown = 0 - if(href_list["logout"]) - authenticated = 0 + if("dept") + var/lastdestination = destination + destination = input(usr, "Which department?", "Choose a department", "") as null|anything in (alldepartments + admin_departments) + if(!destination) + destination = lastdestination - SSnanoui.update_uis(src) + return TRUE /obj/machinery/photocopier/faxmachine/attackby(obj/item/O as obj, mob/user as mob) if(O.is_multitool() && panel_open) diff --git a/code/modules/paperwork/photocopier.dm b/code/modules/paperwork/photocopier.dm index 5bf6a9102a..07009a99c0 100644 --- a/code/modules/paperwork/photocopier.dm +++ b/code/modules/paperwork/photocopier.dm @@ -33,33 +33,71 @@ /obj/machinery/photocopier/attack_hand(mob/user as mob) user.set_machine(src) - ui_interact(user) + tgui_interact(user) -/** - * Display the NanoUI window for the photocopier. - * - * See NanoUI documentation for details. - */ -/obj/machinery/photocopier/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - user.set_machine(src) - - var/list/data = list() - data["copyItem"] = copyitem - data["assPresent"] = has_buckled_mobs() - data["toner"] = toner - data["copies"] = copies - data["maxCopies"] = maxcopies - if(istype(user,/mob/living/silicon)) - data["isSilicon"] = 1 - else - data["isSilicon"] = null - - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - ui = new(user, src, ui_key, "photocopier.tmpl", src.name, 300, 250) - ui.set_initial_data(data) +/obj/machinery/photocopier/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "Photocopier", name) ui.open() - ui.set_auto_update(10) + +/obj/machinery/photocopier/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state) + var/list/data = ..() + + data["has_item"] = copyitem || has_buckled_mobs() // VOREStation Edit: Ass copying + data["isAI"] = issilicon(user) + data["can_AI_print"] = (toner >= 5) + data["has_toner"] = !!toner + data["current_toner"] = toner + data["max_toner"] = 40 + data["num_copies"] = copies + data["max_copies"] = maxcopies + + return data + +/obj/machinery/photocopier/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) + if(..()) + return TRUE + + switch(action) + if("make_copy") + addtimer(CALLBACK(src, .proc/copy_operation, usr), 0) + . = TRUE + if("remove") + if(copyitem) + copyitem.loc = usr.loc + usr.put_in_hands(copyitem) + to_chat(usr, "You take \the [copyitem] out of \the [src].") + copyitem = null + else if(has_buckled_mobs()) + to_chat(buckled_mobs[1], "You feel a slight pressure on your ass.") // It can't eject your asscheeks, but it'll try. + . = TRUE + if("set_copies") + copies = clamp(text2num(params["num_copies"]), 1, maxcopies) + . = TRUE + if("ai_photo") + if(!issilicon(usr)) + return + if(stat & (BROKEN|NOPOWER)) + return + + if(toner >= 5) + var/mob/living/silicon/tempAI = usr + var/obj/item/device/camera/siliconcam/camera = tempAI.aiCamera + + if(!camera) + return + var/obj/item/weapon/photo/selection = camera.selectpicture() + if (!selection) + return + + var/obj/item/weapon/photo/p = photocopy(selection) + if (p.desc == "") + p.desc += "Copied by [tempAI.name]" + else + p.desc += " - Copied by [tempAI.name]" + toner -= 5 + . = TRUE /obj/machinery/photocopier/proc/copy_operation(var/mob/user) if(copying) @@ -104,51 +142,6 @@ use_power(active_power_usage) copying = FALSE -/obj/machinery/photocopier/Topic(href, href_list) - if(href_list["copy"]) - if(stat & (BROKEN|NOPOWER)) - return - addtimer(CALLBACK(src, .proc/copy_operation, usr), 0) - - else if(href_list["remove"]) - if(copyitem) - copyitem.loc = usr.loc - usr.put_in_hands(copyitem) - to_chat(usr, "You take \the [copyitem] out of \the [src].") - copyitem = null - else if(has_buckled_mobs()) - to_chat(buckled_mobs[1], "You feel a slight pressure on your ass.") // It can't eject your asscheeks, but it'll try. - return TOPIC_REFRESH - else if(href_list["min"]) - if(copies > 1) - copies-- - else if(href_list["add"]) - if(copies < maxcopies) - copies++ - else if(href_list["aipic"]) - if(!istype(usr,/mob/living/silicon)) return - if(stat & (BROKEN|NOPOWER)) return - - if(toner >= 5) - var/mob/living/silicon/tempAI = usr - var/obj/item/device/camera/siliconcam/camera = tempAI.aiCamera - - if(!camera) - return - var/obj/item/weapon/photo/selection = camera.selectpicture() - if (!selection) - return - - var/obj/item/weapon/photo/p = photocopy(selection) - if (p.desc == "") - p.desc += "Copied by [tempAI.name]" - else - p.desc += " - Copied by [tempAI.name]" - toner -= 5 - sleep(15) - - SSnanoui.update_uis(src) - /obj/machinery/photocopier/attackby(obj/item/O as obj, mob/user as mob) if(istype(O, /obj/item/weapon/paper) || istype(O, /obj/item/weapon/photo) || istype(O, /obj/item/weapon/paper_bundle)) if(!copyitem) diff --git a/code/modules/pda/ai.dm b/code/modules/pda/ai.dm index b8a0d99a39..9072eef96e 100644 --- a/code/modules/pda/ai.dm +++ b/code/modules/pda/ai.dm @@ -4,7 +4,12 @@ icon_state = "NONE" ttone = "data" detonate = 0 - + touch_silent = TRUE + programs = list( + new/datum/data/pda/app/main_menu, + new/datum/data/pda/app/notekeeper, + new/datum/data/pda/app/news, + new/datum/data/pda/app/messenger) /obj/item/device/pda/ai/proc/set_name_and_job(newname as text, newjob as text, newrank as null|text) owner = newname @@ -16,70 +21,18 @@ name = newname + " (" + ownjob + ")" //AI verb and proc for sending PDA messages. -/obj/item/device/pda/ai/verb/cmd_send_pdamesg() +/obj/item/device/pda/ai/verb/cmd_pda_open_ui() set category = "AI IM" - set name = "Send PDA Message" + set name = "Use PDA" set src in usr if(!can_use()) return - var/datum/data/pda/app/messenger/M = find_program(/datum/data/pda/app/messenger) - if(!M) - to_chat(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_toggle_pda_receiver() - set category = "AI IM" - set name = "Toggle Sender/Receiver" - set src in usr - - if(!can_use()) - return - var/datum/data/pda/app/messenger/M = find_program(/datum/data/pda/app/messenger) - M.toff = !M.toff - to_chat(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(!can_use()) - return - var/datum/data/pda/app/messenger/M = find_program(/datum/data/pda/app/messenger) - M.notify_silent = !M.notify_silent - to_chat(usr, "PDA ringer toggled [(M.notify_silent ? "Off" : "On")]!") - -/obj/item/device/pda/ai/verb/cmd_show_message_log() - set category = "AI IM" - set name = "Show Message Log" - set src in usr - - if(!can_use()) - return - var/datum/data/pda/app/messenger/M = find_program(/datum/data/pda/app/messenger) - if(!M) - to_chat(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") - + tgui_interact(usr) /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-- @@ -90,11 +43,6 @@ /obj/item/device/pda/ai/pai ttone = "assist" var/our_owner = null // Ref to a pAI - touch_silent = TRUE - programs = list( - new/datum/data/pda/app/main_menu, - new/datum/data/pda/app/notekeeper, - new/datum/data/pda/app/messenger) /obj/item/device/pda/ai/pai/New(mob/living/silicon/pai/P) if(istype(P)) diff --git a/code/modules/pda/pda_tgui.dm b/code/modules/pda/pda_tgui.dm index 4937d42325..0d70b6db02 100644 --- a/code/modules/pda/pda_tgui.dm +++ b/code/modules/pda/pda_tgui.dm @@ -7,10 +7,10 @@ if(!can_use()) . = min(., STATUS_UPDATE) -/obj/item/device/pda/tgui_interact(mob/user, datum/tgui/ui) +/obj/item/device/pda/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui) ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, "Pda", "Personal Data Assistant") + ui = new(user, src, "Pda", "Personal Data Assistant", parent_ui) ui.open() /obj/item/device/pda/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state) diff --git a/code/modules/power/batteryrack.dm b/code/modules/power/batteryrack.dm index f6bc1c9ff6..dc1dbe7e58 100644 --- a/code/modules/power/batteryrack.dm +++ b/code/modules/power/batteryrack.dm @@ -25,6 +25,7 @@ var/equalise = 0 // If true try to equalise charge between cells var/icon_update = 0 // Timer in ticks for icon update. var/ui_tick = 0 + should_be_mapped = TRUE /obj/machinery/power/smes/batteryrack/New() @@ -113,6 +114,8 @@ if(equalise) // Now try to get least charged cell and use the power from it. var/obj/item/weapon/cell/CL = get_least_charged_cell() + if(!CL) + return amount -= CL.give(amount) if(!amount) return @@ -209,8 +212,43 @@ celldiff = min(min(celldiff, most.charge), least.maxcharge - least.charge) least.give(most.use(celldiff)) -/obj/machinery/power/smes/batteryrack/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - var/data[0] +/obj/machinery/power/smes/batteryrack/dismantle() + for(var/obj/item/weapon/cell/C in internal_cells) + C.forceMove(get_turf(src)) + internal_cells -= C + return ..() + +/obj/machinery/power/smes/batteryrack/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob) + if(istype(W, /obj/item/weapon/cell)) // ID Card, try to insert it. + if(insert_cell(W, user)) + to_chat(user, "You insert \the [W] into \the [src].") + else + to_chat(user, "\The [src] has no empty slot for \the [W]") + if(!..()) + return 0 + if(default_deconstruction_crowbar(user, W)) + return + if(default_part_replacement(user, W)) + return + +/obj/machinery/power/smes/batteryrack/inputting() + return + +/obj/machinery/power/smes/batteryrack/outputting() + return + +/obj/machinery/power/smes/batteryrack/attack_hand(var/mob/user) + tgui_interact(user) + +/obj/machinery/power/smes/batteryrack/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "Batteryrack", name) + ui.open() + +/obj/machinery/power/smes/batteryrack/tgui_data(mob/user) + // DO NOT CALL PARENT. + var/list/data = list() data["mode"] = mode data["transfer_max"] = max_transfer_rate @@ -238,75 +276,44 @@ cells += list(cell) data["cells_list"] = cells - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - ui = new(user, src, ui_key, "psu.tmpl", "Cell Rack PSU", 500, 430) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) + return data -/obj/machinery/power/smes/batteryrack/dismantle() - for(var/obj/item/weapon/cell/C in internal_cells) - C.forceMove(get_turf(src)) - internal_cells -= C - return ..() - -/obj/machinery/power/smes/batteryrack/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob) - if(!..()) - return 0 - if(default_deconstruction_crowbar(user, W)) - return - if(default_part_replacement(user, W)) - return - if(istype(W, /obj/item/weapon/cell)) // ID Card, try to insert it. - if(insert_cell(W, user)) - to_chat(user, "You insert \the [W] into \the [src].") - else - to_chat(user, "\The [src] has no empty slot for \the [W]") - -/obj/machinery/power/smes/batteryrack/attack_hand(var/mob/user) - ui_interact(user) - -/obj/machinery/power/smes/batteryrack/inputting() - return - -/obj/machinery/power/smes/batteryrack/outputting() - return - -/obj/machinery/power/smes/batteryrack/Topic(href, href_list) +/obj/machinery/power/smes/batteryrack/tgui_act(action, list/params) // ..() would respond to those topic calls, but we don't want to use them at all. // Calls to these shouldn't occur anyway, due to usage of different nanoUI, but // it's here in case someone decides to try hrefhacking/modified templates. - if(href_list["input"] || href_list["output"]) - return 1 + if(!(action in list("disable", "enable", "equaliseon", "equaliseoff", "ejectcell"))) + return TRUE if(..()) - return 1 - if( href_list["disable"] ) - update_io(0) - return 1 - else if( href_list["enable"] ) - update_io(between(1, text2num(href_list["enable"]), 3)) - return 1 - else if( href_list["equaliseon"] ) - equalise = 1 - return 1 - else if( href_list["equaliseoff"] ) - equalise = 0 - return 1 - else if( href_list["ejectcell"] ) - var/obj/item/weapon/cell/C - for(var/obj/item/weapon/cell/CL in internal_cells) - if(CL.c_uid == text2num(href_list["ejectcell"])) - C = CL - break + return TRUE - if(!istype(C)) - return 1 + switch(action) + if("disable") + update_io(0) + return TRUE + if("enable") + update_io(between(1, text2num(params["enable"]), 3)) + return TRUE + if("equaliseon") + equalise = 1 + return TRUE + if("equaliseoff") + equalise = 0 + return TRUE + if("ejectcell") + var/obj/item/weapon/cell/C + for(var/obj/item/weapon/cell/CL in internal_cells) + if(CL.c_uid == text2num(params["ejectcell"])) + C = CL + break - C.forceMove(get_turf(src)) - internal_cells -= C - update_icon() - RefreshParts() - update_maxcharge() - return 1 \ No newline at end of file + if(!istype(C)) + return TRUE + + C.forceMove(get_turf(src)) + internal_cells -= C + update_icon() + RefreshParts() + update_maxcharge() + return TRUE \ No newline at end of file diff --git a/code/modules/power/grid_checker.dm b/code/modules/power/grid_checker.dm index 224eade429..53766098f0 100644 --- a/code/modules/power/grid_checker.dm +++ b/code/modules/power/grid_checker.dm @@ -59,7 +59,7 @@ if(opened) wires.Interact(user) - return ui_interact(user) + return tgui_interact(user) /obj/machinery/power/grid_checker/proc/power_failure(var/announce = TRUE) if(announce) diff --git a/code/modules/power/turbine.dm b/code/modules/power/turbine.dm index 2caa008f0c..1d5262044e 100644 --- a/code/modules/power/turbine.dm +++ b/code/modules/power/turbine.dm @@ -345,59 +345,59 @@ /obj/machinery/computer/turbine_computer/attack_hand(var/mob/user as mob) if((. = ..())) return - src.interact(user) + tgui_interact(user) -/obj/machinery/computer/turbine_computer/interact(mob/user) - return ui_interact(user) +/obj/machinery/computer/turbine_computer/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "TurbineControl", name) + ui.open() -/obj/machinery/computer/turbine_computer/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) +/obj/machinery/computer/turbine_computer/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state) var/list/data = list() data["connected"] = (compressor && compressor.turbine) ? TRUE : FALSE data["compressor_broke"] = (!compressor || (compressor.stat & BROKEN)) ? TRUE : FALSE data["turbine_broke"] = (!compressor || !compressor.turbine || (compressor.turbine.stat & BROKEN)) ? TRUE : FALSE data["broken"] = (data["compressor_broke"] || data["turbine_broke"]) data["door_status"] = door_status ? TRUE : FALSE + + data["online"] = FALSE + data["power"] = 0 + data["rpm"] = 0 + data["temp"] = 0 + if(compressor && compressor.turbine) data["online"] = compressor.starter - data["power"] = DisplayPower(compressor.turbine.lastgen) + data["power"] = compressor.turbine.lastgen // DisplayPower data["rpm"] = compressor.rpm data["temp"] = compressor.gas_contained.temperature - // update the ui if it exists, returns null if no ui is passed/found - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - // 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, "turbine_computer.tmpl", name, 520, 440) - // 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(TRUE) + return data -/obj/machinery/computer/turbine_computer/Topic(href, href_list) +/obj/machinery/computer/turbine_computer/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) if(..()) - return - if(href_list["power-on"]) - if(compressor && compressor.turbine) - compressor.starter = TRUE + return TRUE + + switch(action) + if("power-on") + if(compressor && compressor.turbine) + compressor.starter = TRUE + . = TRUE + if("power-off") + if(compressor && compressor.turbine) + compressor.starter = FALSE + . = TRUE + if("reconnect") + locate_machinery() . = TRUE - else if(href_list["power-off"]) - if(compressor && compressor.turbine) - compressor.starter = FALSE + if("doors") + door_status = !door_status + for(var/obj/machinery/door/blast/D in src.doors) + if (door_status) + spawn(0) D.close() + else + spawn(0)D.open() . = TRUE - else if(href_list["reconnect"]) - locate_machinery() - . = TRUE - else if(href_list["doors"]) - door_status = !door_status - for(var/obj/machinery/door/blast/D in src.doors) - if (door_status) - spawn(0) D.close() - else - spawn(0)D.open() - . = TRUE #undef COMPFRICTION #undef COMPSTARTERLOAD diff --git a/code/modules/reagents/dispenser/dispenser2_energy.dm b/code/modules/reagents/dispenser/dispenser2_energy.dm index 84c5260c3f..b0dec9f65b 100644 --- a/code/modules/reagents/dispenser/dispenser2_energy.dm +++ b/code/modules/reagents/dispenser/dispenser2_energy.dm @@ -25,7 +25,7 @@ C.reagents.add_reagent(id, to_restore) . = 1 if(.) - SSnanoui.update_uis(src) + SStgui.update_uis(src) /obj/machinery/chemical_dispenser dispense_reagents = list( diff --git a/code/modules/resleeving/infomorph.dm b/code/modules/resleeving/infomorph.dm index 248444f1df..fed79fe078 100644 --- a/code/modules/resleeving/infomorph.dm +++ b/code/modules/resleeving/infomorph.dm @@ -147,9 +147,9 @@ var/list/infomorph_emotions = list( return 0 ..() -/mob/living/silicon/infomorph/default_can_use_topic(var/src_object) +/mob/living/silicon/infomorph/default_can_use_tgui_topic(var/src_object) if(src_object in src) - return shared_nano_interaction() + return shared_tgui_interaction() /////////// DAMAGES /mob/living/silicon/infomorph/emp_act(severity) @@ -190,7 +190,7 @@ var/list/infomorph_emotions = list( medicalActive1 = null medicalActive2 = null medical_cannotfind = 0 - SSnanoui.update_uis(src) + SStgui.update_uis(src) to_chat(usr, "You reset your record-viewing software.") /* @@ -463,94 +463,81 @@ var/global/list/default_infomorph_software = list() set category = "Card Commands" set name = "Software Interface" - ui_interact(src) + tgui_interact(src) -/mob/living/silicon/infomorph/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, key_state = self_state) - if(user != src) - if(ui) ui.set_status(STATUS_CLOSE, 0) - return +/mob/living/silicon/infomorph/tgui_state(mob/user) + return GLOB.tgui_self_state - if(ui_key != "main") - var/datum/infomorph_software/S = software[ui_key] - if(S && !S.toggle) - S.on_ui_interact(src, ui, force_open) - else - if(ui) ui.set_status(STATUS_CLOSE, 0) - return - - var/data[0] +/mob/living/silicon/infomorph/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "pAIInterface", "Card Software Interface") + ui.open() +/mob/living/silicon/infomorph/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state) + var/list/data = ..() + // Software we have bought - var/bought_software[0] + var/list/bought_software = list() // Software we have not bought - var/not_bought_software[0] + var/list/not_bought_software = list() for(var/key in infomorph_software_by_key) var/datum/infomorph_software/S = infomorph_software_by_key[key] - var/software_data[0] + var/list/software_data = list() software_data["name"] = S.name software_data["id"] = S.id if(key in software) software_data["on"] = S.is_active(src) - bought_software[++bought_software.len] = software_data + bought_software.Add(list(software_data)) else software_data["ram"] = S.ram_cost - not_bought_software[++not_bought_software.len] = software_data + not_bought_software.Add(list(software_data)) data["bought"] = bought_software data["not_bought"] = not_bought_software data["available_ram"] = ram // Emotions - var/emotions[0] + var/list/emotions = list() for(var/name in infomorph_emotions) - var/emote[0] + var/list/emote = list() emote["name"] = name emote["id"] = infomorph_emotions[name] - emotions[++emotions.len] = emote + emotions.Add(list(emote)) data["emotions"] = emotions data["current_emotion"] = card.current_emotion - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open, key_state) - if (!ui) - ui = new(user, src, ui_key, "pai_interface.tmpl", "Card Software Interface", 450, 600, state = key_state) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) + return data -/mob/living/silicon/infomorph/Topic(href, href_list) - . = ..() - if(.) return +/mob/living/silicon/infomorph/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) + if(..()) + return TRUE - if(href_list["software"]) - var/soft = href_list["software"] - var/datum/infomorph_software/S = software[soft] - if(S.toggle) - S.toggle(src) - else - ui_interact(src, ui_key = soft) - return 1 + switch(action) + if("software") + var/soft = params["software"] + var/datum/infomorph_software/S = software[soft] + if(S.toggle) + S.toggle(src) + else + S.tgui_interact(src, parent_ui = ui) + return TRUE - else if(href_list["stopic"]) - var/soft = href_list["stopic"] - var/datum/infomorph_software/S = software[soft] - if(S) - return S.Topic(href, href_list) + if("purchase") + var/soft = params["purchase"] + var/datum/infomorph_software/S = infomorph_software_by_key[soft] + if(S && (ram >= S.ram_cost)) + ram -= S.ram_cost + software[S.id] = S + return TRUE - else if(href_list["purchase"]) - var/soft = href_list["purchase"] - var/datum/infomorph_software/S = infomorph_software_by_key[soft] - if(S && (ram >= S.ram_cost)) - ram -= S.ram_cost - software[S.id] = S - return 1 - - else if(href_list["image"]) - var/img = href_list["image"] - if(img) - card.setEmotion(img) - return 1 + if("image") + var/img = text2num(params["image"]) + if(img) + card.setEmotion(img) + return TRUE /mob/living/silicon/infomorph/examine(mob/user) . = ..(user, infix = ", personal AI") diff --git a/code/modules/resleeving/infomorph_software.dm b/code/modules/resleeving/infomorph_software.dm index 2d2439b614..67a2bd47f9 100644 --- a/code/modules/resleeving/infomorph_software.dm +++ b/code/modules/resleeving/infomorph_software.dm @@ -12,35 +12,38 @@ // Whether pAIs should automatically receive this module at no cost var/default = 0 - proc/on_ui_interact(mob/living/silicon/infomorph/user, datum/nanoui/ui=null, force_open=1) - return +/datum/infomorph_software/tgui_state(mob/user) + return GLOB.tgui_always_state - proc/toggle(mob/living/silicon/infomorph/user) - return +/datum/infomorph_software/tgui_status(mob/user) + if(!istype(user, /mob/living/silicon/infomorph)) + return STATUS_CLOSE + return ..() - proc/is_active(mob/living/silicon/infomorph/user) - return 0 +/datum/infomorph_software/proc/toggle(mob/living/silicon/infomorph/user) + return + +/datum/infomorph_software/proc/is_active(mob/living/silicon/infomorph/user) + return 0 /datum/infomorph_software/crew_manifest name = "Crew Manifest" - ram_cost = 15 + ram_cost = 5 id = "manifest" toggle = 0 - on_ui_interact(mob/living/silicon/infomorph/user, datum/nanoui/ui=null, force_open=1) +/datum/infomorph_software/crew_manifest/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "CrewManifest", name, parent_ui) + ui.open() + +/datum/infomorph_software/crew_manifest/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state) + var/list/data = ..() + if(data_core) data_core.get_manifest_list() - - var/data[0] - // This is dumb, but NanoUI breaks if it has no data to send - data["manifest"] = PDA_Manifest - - ui = SSnanoui.try_update_ui(user, user, id, ui, data, force_open) - if(!ui) - // Don't copy-paste this unless you're making a pAI software module! - ui = new(user, user, id, "pai_manifest.tmpl", "Crew Manifest", 450, 600) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) + data["manifest"] = PDA_Manifest + return data /datum/infomorph_software/med_records name = "Medical Records" @@ -48,53 +51,55 @@ id = "med_records" toggle = 0 - on_ui_interact(mob/living/silicon/infomorph/user, datum/nanoui/ui=null, force_open=1) - var/data[0] +/datum/infomorph_software/med_records/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "pAIMedrecords", name, parent_ui) + ui.open() - var/records[0] - for(var/datum/data/record/general in sortRecord(data_core.general)) - var/record[0] - record["name"] = general.fields["name"] - record["ref"] = "\ref[general]" - records[++records.len] = record +/datum/infomorph_software/med_records/tgui_data(mob/living/silicon/infomorph/user, datum/tgui/ui, datum/tgui_state/state) + var/list/data = ..() + + var/list/records = list() + for(var/datum/data/record/general in sortRecord(data_core.general)) + var/list/record = list() + record["name"] = general.fields["name"] + record["ref"] = "\ref[general]" + records.Add(list(record)) - data["records"] = records + data["records"] = records - var/datum/data/record/G = user.medicalActive1 - var/datum/data/record/M = user.medicalActive2 - data["general"] = G ? G.fields : null - data["medical"] = M ? M.fields : null - data["could_not_find"] = user.medical_cannotfind + var/datum/data/record/G = user.medicalActive1 + var/datum/data/record/M = user.medicalActive2 + data["general"] = G ? G.fields : null + data["medical"] = M ? M.fields : null + data["could_not_find"] = user.medical_cannotfind - ui = SSnanoui.try_update_ui(user, user, id, ui, data, force_open) - if(!ui) - // Don't copy-paste this unless you're making a pAI software module! - ui = new(user, user, id, "pai_medrecords.tmpl", "Medical Records", 450, 600) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) + return data - Topic(href, href_list) - var/mob/living/silicon/infomorph/P = usr - if(!istype(P)) return +/datum/infomorph_software/med_records/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) + . = ..() + var/mob/living/silicon/infomorph/P = usr + if(!istype(P)) + return - if(href_list["select"]) - var/datum/data/record/record = locate(href_list["select"]) - if(record) - var/datum/data/record/R = record - var/datum/data/record/M = null - if (!( data_core.general.Find(R) )) - P.medical_cannotfind = 1 - else - P.medical_cannotfind = 0 - 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 - P.medicalActive1 = R - P.medicalActive2 = M - else + if(action == "select") + var/datum/data/record/record = locate(params["select"]) + if(record) + var/datum/data/record/R = record + var/datum/data/record/M = null + if (!( data_core.general.Find(R) )) P.medical_cannotfind = 1 - return 1 + else + P.medical_cannotfind = 0 + 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 + P.medicalActive1 = R + P.medicalActive2 = M + else + P.medical_cannotfind = 1 + return 1 /datum/infomorph_software/sec_records name = "Security Records" @@ -102,57 +107,59 @@ id = "sec_records" toggle = 0 - on_ui_interact(mob/living/silicon/infomorph/user, datum/nanoui/ui=null, force_open=1) - var/data[0] +/datum/infomorph_software/sec_records/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "pAISecrecords", name, parent_ui) + ui.open() - var/records[0] - for(var/datum/data/record/general in sortRecord(data_core.general)) - var/record[0] - record["name"] = general.fields["name"] - record["ref"] = "\ref[general]" - records[++records.len] = record +/datum/infomorph_software/sec_records/tgui_data(mob/living/silicon/infomorph/user, datum/tgui/ui, datum/tgui_state/state) + var/list/data = ..() + + var/list/records = list() + for(var/datum/data/record/general in sortRecord(data_core.general)) + var/list/record = list() + record["name"] = general.fields["name"] + record["ref"] = "\ref[general]" + records.Add(list(record)) - data["records"] = records + data["records"] = records - var/datum/data/record/G = user.securityActive1 - var/datum/data/record/S = user.securityActive2 - data["general"] = G ? G.fields : null - data["security"] = S ? S.fields : null - data["could_not_find"] = user.security_cannotfind + var/datum/data/record/G = user.securityActive1 + var/datum/data/record/S = user.securityActive2 + data["general"] = G ? G.fields : null + data["security"] = S ? S.fields : null + data["could_not_find"] = user.security_cannotfind - ui = SSnanoui.try_update_ui(user, user, id, ui, data, force_open) - if(!ui) - // Don't copy-paste this unless you're making a pAI software module! - ui = new(user, user, id, "pai_secrecords.tmpl", "Security Records", 450, 600) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) + return data - Topic(href, href_list) - var/mob/living/silicon/infomorph/P = usr - if(!istype(P)) return +/datum/infomorph_software/sec_records/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) + . = ..() + var/mob/living/silicon/infomorph/P = usr + if(!istype(P)) + return - if(href_list["select"]) - var/datum/data/record/record = locate(href_list["select"]) - if(record) - var/datum/data/record/R = record - var/datum/data/record/S = null - if (!( data_core.general.Find(R) )) - P.securityActive1 = null - P.securityActive2 = null - P.security_cannotfind = 1 - else - P.security_cannotfind = 0 - 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 - P.securityActive1 = R - P.securityActive2 = S - else + if(action == "select") + var/datum/data/record/record = locate(params["select"]) + if(record) + var/datum/data/record/R = record + var/datum/data/record/S = null + if (!( data_core.general.Find(R) )) P.securityActive1 = null P.securityActive2 = null P.security_cannotfind = 1 - return 1 + else + P.security_cannotfind = 0 + 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 + P.securityActive1 = R + P.securityActive2 = S + else + P.securityActive1 = null + P.securityActive2 = null + P.security_cannotfind = 1 + return TRUE /datum/infomorph_software/door_jack name = "Door Jack" @@ -160,44 +167,45 @@ id = "door_jack" toggle = 0 - on_ui_interact(mob/living/silicon/infomorph/user, datum/nanoui/ui=null, force_open=1) - var/data[0] +/datum/infomorph_software/door_jack/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "pAIDoorjack", "Door Jack", parent_ui) + ui.open() - data["cable"] = user.cable != null - data["machine"] = user.cable && (user.cable.machine != null) - data["inprogress"] = user.hackdoor != null - data["progress_a"] = round(user.hackprogress) - data["progress_b"] = user.hackprogress % 10 - data["aborted"] = user.hack_aborted +/datum/infomorph_software/door_jack/tgui_data(mob/living/silicon/infomorph/user, datum/tgui/ui, datum/tgui_state/state) + var/list/data = ..() - ui = SSnanoui.try_update_ui(user, user, id, ui, data, force_open) - if(!ui) - // Don't copy-paste this unless you're making a pAI software module! - ui = new(user, user, id, "pai_doorjack.tmpl", "Door Jack", 300, 150) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) + data["cable"] = user.cable != null + data["machine"] = user.cable && (user.cable.machine != null) + data["inprogress"] = user.hackdoor != null + data["progress_a"] = round(user.hackprogress / 10) + data["progress_b"] = user.hackprogress % 10 + data["aborted"] = user.hack_aborted - Topic(href, href_list) - var/mob/living/silicon/infomorph/P = usr - if(!istype(P)) return + return data - if(href_list["jack"]) +/datum/infomorph_software/door_jack/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) + var/mob/living/silicon/infomorph/P = usr + if(!istype(P) || ..()) + return TRUE + + switch(action) + if("jack") if(P.cable && P.cable.machine) P.hackdoor = P.cable.machine P.hackloop() return 1 - else if(href_list["cancel"]) + if("cancel") P.hackdoor = null return 1 - else if(href_list["cable"]) + if("cable") var/turf/T = get_turf(P) P.hack_aborted = 0 P.cable = new /obj/item/weapon/pai_cable(T) - if(ishuman(P.card.loc)) - var/mob/living/carbon/human/H = P.card.loc - H.put_in_any_hand_if_possible(P.cable) - T.visible_message("A port on \the [P] opens to reveal \the [P.cable].") + for(var/mob/M in viewers(T)) + M.show_message("A port on [P] opens to reveal [P.cable], which promptly falls to the floor.", 3, + "You hear the soft click of something light and hard falling to the ground.", 2) return 1 /mob/living/silicon/infomorph/proc/hackloop() @@ -239,43 +247,54 @@ /datum/infomorph_software/atmosphere_sensor name = "Atmosphere Sensor" - ram_cost = 15 + ram_cost = 5 id = "atmos_sense" toggle = 0 - on_ui_interact(mob/living/silicon/infomorph/user, datum/nanoui/ui=null, force_open=1) - var/data[0] +/datum/infomorph_software/atmosphere_sensor/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "pAIAtmos", name, parent_ui) + ui.open() - var/turf/T = get_turf_or_move(user.loc) - if(!T) - data["reading"] = 0 - data["pressure"] = 0 - data["temperature"] = 0 - data["temperatureC"] = 0 - data["gas"] = list() - else - var/datum/gas_mixture/env = T.return_air() - data["reading"] = 1 - var/pres = env.return_pressure() * 10 - data["pressure"] = "[round(pres/10)].[pres%10]" - data["temperature"] = round(env.temperature) - data["temperatureC"] = round(env.temperature-T0C) +/datum/infomorph_software/atmosphere_sensor/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state) + var/list/data = ..() - var/t_moles = env.total_moles - var/gases[0] - for(var/g in env.gas) - var/gas[0] - gas["name"] = gas_data.name[g] - gas["percent"] = round((env.gas[g] / t_moles) * 100) - gases[++gases.len] = gas - data["gas"] = gases + var/list/results = list() + var/turf/T = get_turf(user) + 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.gas["oxygen"]/total_moles + var/n2_level = environment.gas["nitrogen"]/total_moles + var/co2_level = environment.gas["carbon_dioxide"]/total_moles + var/phoron_level = environment.gas["phoron"]/total_moles + var/unknown_level = 1-(o2_level+n2_level+co2_level+phoron_level) - ui = SSnanoui.try_update_ui(user, user, id, ui, data, force_open) - if(!ui) - // Don't copy-paste this unless you're making a pAI software module! - ui = new(user, user, id, "pai_atmosphere.tmpl", "Atmosphere Sensor", 350, 300) - ui.set_initial_data(data) - ui.open() + // entry is what the element is describing + // Type identifies which unit or other special characters to use + // Val is the information reported + // Bad_high/_low are the values outside of which the entry reports as dangerous + // Poor_high/_low are the values outside of which the entry reports as unideal + // Values were extracted from the template itself + results = list( + list("entry" = "Pressure", "units" = "kPa", "val" = "[round(pressure,0.1)]", "bad_high" = 120, "poor_high" = 110, "poor_low" = 95, "bad_low" = 80), + list("entry" = "Temperature", "units" = "°C", "val" = "[round(environment.temperature-T0C,0.1)]", "bad_high" = 35, "poor_high" = 25, "poor_low" = 15, "bad_low" = 5), + list("entry" = "Oxygen", "units" = "kPa", "val" = "[round(o2_level*100,0.1)]", "bad_high" = 140, "poor_high" = 135, "poor_low" = 19, "bad_low" = 17), + list("entry" = "Nitrogen", "units" = "kPa", "val" = "[round(n2_level*100,0.1)]", "bad_high" = 105, "poor_high" = 85, "poor_low" = 50, "bad_low" = 40), + list("entry" = "Carbon Dioxide", "units" = "kPa", "val" = "[round(co2_level*100,0.1)]", "bad_high" = 10, "poor_high" = 5, "poor_low" = 0, "bad_low" = 0), + list("entry" = "Phoron", "units" = "kPa", "val" = "[round(phoron_level*100,0.01)]", "bad_high" = 0.5, "poor_high" = 0, "poor_low" = 0, "bad_low" = 0), + list("entry" = "Other", "units" = "kPa", "val" = "[round(unknown_level, 0.01)]", "bad_high" = 1, "poor_high" = 0.5, "poor_low" = 0, "bad_low" = 0) + ) + + if(isnull(results)) + results = list(list("entry" = "pressure", "units" = "kPa", "val" = "0", "bad_high" = 120, "poor_high" = 110, "poor_low" = 95, "bad_low" = 80)) + + data["aircontents"] = results + + return data /datum/infomorph_software/ar_hud name = "AR HUD" @@ -302,45 +321,56 @@ is_active(mob/living/silicon/infomorph/user) return user.translator.listening + /datum/infomorph_software/signaller - name = "Remote Signaller" - ram_cost = 15 + name = "Remote Signaler" + ram_cost = 5 id = "signaller" toggle = 0 - on_ui_interact(mob/living/silicon/infomorph/user, datum/nanoui/ui=null, force_open=1) - var/data[0] +/datum/infomorph_software/signaller/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "Signaler", "Signaler", parent_ui) + ui.open() - data["frequency"] = format_frequency(user.sradio.frequency) - data["code"] = user.sradio.code +/datum/infomorph_software/signaller/tgui_data(mob/living/silicon/infomorph/user, datum/tgui/ui, datum/tgui_state/state) + var/list/data = ..() + + var/obj/item/radio/integrated/signal/R = user.sradio - ui = SSnanoui.try_update_ui(user, user, id, ui, data, force_open) - if(!ui) - // Don't copy-paste this unless you're making a pAI software module! - ui = new(user, user, id, "pai_signaller.tmpl", "Signaller", 320, 150) - ui.set_initial_data(data) - ui.open() + data["frequency"] = R.frequency + data["minFrequency"] = RADIO_LOW_FREQ + data["maxFrequency"] = RADIO_HIGH_FREQ + data["code"] = R.code - Topic(href, href_list) - var/mob/living/silicon/infomorph/P = usr - if(!istype(P)) return + return data - if(href_list["send"]) - P.sradio.send_signal("ACTIVATE") - for(var/mob/O in hearers(1, P.loc)) - O.show_message("[bicon(P)] *beep* *beep*", 3, "*beep* *beep*", 2) - return 1 +/datum/infomorph_software/signaller/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) + if(..()) + return TRUE - else if(href_list["freq"]) - var/new_frequency = (P.sradio.frequency + text2num(href_list["freq"])) - if(new_frequency < PUBLIC_LOW_FREQ || new_frequency > PUBLIC_HIGH_FREQ) - new_frequency = sanitize_frequency(new_frequency) - P.sradio.set_frequency(new_frequency) - return 1 + var/mob/living/silicon/infomorph/user = usr + if(istype(user)) + var/obj/item/radio/integrated/signal/R = user.sradio - else if(href_list["code"]) - P.sradio.code += text2num(href_list["code"]) - P.sradio.code = round(P.sradio.code) - P.sradio.code = min(100, P.sradio.code) - P.sradio.code = max(1, P.sradio.code) - return 1 + switch(action) + if("signal") + spawn(0) + R.send_signal("ACTIVATE") + for(var/mob/O in hearers(1, R.loc)) + O.show_message("[bicon(R)] *beep* *beep*", 3, "*beep* *beep*", 2) + if("freq") + var/frequency = unformat_frequency(params["freq"]) + frequency = sanitize_frequency(frequency, RADIO_LOW_FREQ, RADIO_HIGH_FREQ) + R.set_frequency(frequency) + . = TRUE + if("code") + R.code = clamp(round(text2num(params["code"])), 1, 100) + . = TRUE + if("reset") + if(params["reset"] == "freq") + R.set_frequency(initial(R.frequency)) + else + R.code = initial(R.code) + . = TRUE diff --git a/code/modules/resleeving/sleevecard.dm b/code/modules/resleeving/sleevecard.dm index 7da45bbdb1..1fc6b8deca 100644 --- a/code/modules/resleeving/sleevecard.dm +++ b/code/modules/resleeving/sleevecard.dm @@ -1,6 +1,9 @@ /obj/item/device/radio/sleevecard canhear_range = 0 +/obj/item/device/radio/sleevecard/tgui_state(mob/user) + return GLOB.tgui_always_state + /obj/item/device/sleevecard name = "sleevecard" desc = "This KHI-upgraded pAI module has enough capacity to run a whole mind of human-level intelligence." diff --git a/code/modules/shuttles/shuttle_console_multi.dm b/code/modules/shuttles/shuttle_console_multi.dm index 9226caebfb..2e45441b1a 100644 --- a/code/modules/shuttles/shuttle_console_multi.dm +++ b/code/modules/shuttles/shuttle_console_multi.dm @@ -26,7 +26,7 @@ switch(action) if("pick") var/dest_key = input("Choose shuttle destination", "Shuttle Destination") as null|anything in shuttle.get_destinations() - if(dest_key && CanInteract(usr, global.default_state)) + if(dest_key && CanInteract(usr, GLOB.tgui_default_state)) shuttle.set_destination(dest_key, usr) return TRUE diff --git a/code/modules/shuttles/shuttle_emergency.dm b/code/modules/shuttles/shuttle_emergency.dm index b6302a50d1..8a947154a7 100644 --- a/code/modules/shuttles/shuttle_emergency.dm +++ b/code/modules/shuttles/shuttle_emergency.dm @@ -175,84 +175,3 @@ /obj/machinery/computer/shuttle_control/emergency/attackby(obj/item/weapon/W as obj, mob/user as mob) read_authorization(W) ..() - -/obj/machinery/computer/shuttle_control/emergency/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - var/data[0] - var/datum/shuttle/autodock/ferry/emergency/shuttle = SSshuttles.shuttles[shuttle_tag] - if (!istype(shuttle)) - return - - var/shuttle_state - switch(shuttle.moving_status) - if(SHUTTLE_IDLE) shuttle_state = "idle" - if(SHUTTLE_WARMUP) shuttle_state = "warmup" - if(SHUTTLE_INTRANSIT) shuttle_state = "in_transit" - - var/shuttle_status - switch (shuttle.process_state) - if(IDLE_STATE) - if (shuttle.in_use) - shuttle_status = "Busy." - else if (!shuttle.location) - shuttle_status = "Standing by at [station_name()]." - else - shuttle_status = "Standing by at [using_map.dock_name]." - if(WAIT_LAUNCH, FORCE_LAUNCH) - shuttle_status = "Shuttle has received command and will depart shortly." - if(WAIT_ARRIVE) - shuttle_status = "Proceeding to destination." - if(WAIT_FINISH) - shuttle_status = "Arriving at destination now." - - //build a list of authorizations - var/list/auth_list[req_authorizations] - - if (!emagged) - var/i = 1 - for (var/dna_hash in authorized) - auth_list[i++] = list("auth_name"=authorized[dna_hash], "auth_hash"=dna_hash) - - while (i <= req_authorizations) //fill up the rest of the list with blank entries - auth_list[i++] = list("auth_name"="", "auth_hash"=null) - else - for (var/i = 1; i <= req_authorizations; i++) - auth_list[i] = list("auth_name"="ERROR", "auth_hash"=null) - - var/has_auth = has_authorization() - - data = list( - "shuttle_status" = shuttle_status, - "shuttle_state" = shuttle_state, - "has_docking" = shuttle.active_docking_controller? 1 : 0, - "docking_status" = shuttle.active_docking_controller? shuttle.active_docking_controller.get_docking_status() : null, - "docking_override" = shuttle.active_docking_controller? shuttle.active_docking_controller.override_enabled : null, - "can_launch" = shuttle.can_launch(src), - "can_cancel" = shuttle.can_cancel(src), - "can_force" = shuttle.can_force(src), - "auth_list" = auth_list, - "has_auth" = has_auth, - "user" = debug? user : null, - ) - - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - - if (!ui) - ui = new(user, src, ui_key, "escape_shuttle_control_console.tmpl", "Shuttle Control", 470, 420) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) - -/obj/machinery/computer/shuttle_control/emergency/Topic(href, href_list) - if(..()) - return 1 - - if(href_list["removeid"]) - var/dna_hash = href_list["removeid"] - authorized -= dna_hash - - if(!emagged && href_list["scanid"]) - //They selected an empty entry. Try to scan their id. - if (ishuman(usr)) - var/mob/living/carbon/human/H = usr - if (!read_authorization(H.get_active_hand())) //try to read what's in their hand first - read_authorization(H.wear_id) diff --git a/code/modules/telesci/telesci_computer.dm b/code/modules/telesci/telesci_computer.dm index 1119e565ef..d2a6a0a35a 100644 --- a/code/modules/telesci/telesci_computer.dm +++ b/code/modules/telesci/telesci_computer.dm @@ -6,7 +6,7 @@ circuit = /obj/item/weapon/circuitboard/telesci_console var/sending = 1 var/obj/machinery/telepad/telepad = null - var/temp_msg = "Telescience control console initialized.
Welcome." + var/temp_msg = "Telescience control console initialized. Welcome." // VARIABLES // var/teles_left // How many teleports left until it becomes uncalibrated @@ -83,16 +83,21 @@ /obj/machinery/computer/telescience/attack_hand(mob/user) if(..()) return - ui_interact(user) + tgui_interact(user) -/obj/machinery/computer/telescience/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - user.set_machine(src) +/obj/machinery/computer/telescience/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "TelesciConsole", name) + ui.open() - var/data[0] +/obj/machinery/computer/telescience/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state) + var/list/data = list() if(!telepad) in_use = 0 //Yeah so if you deconstruct teleporter while its in the process of shooting it wont disable the console data["noTelepad"] = 1 else + data["noTelepad"] = 0 data["insertedGps"] = inserted_gps data["rotation"] = rotation data["currentZ"] = z_co @@ -110,6 +115,7 @@ //We'll base our options on connected z's or overmap data["sectorOptions"] = using_map.get_map_levels(z, TRUE, overmap_range) + data["lastTeleData"] = null if(last_tele_data) data["lastTeleData"] = list() data["lastTeleData"]["src_x"] = last_tele_data.src_x @@ -117,12 +123,61 @@ data["lastTeleData"]["distance"] = last_tele_data.distance data["lastTeleData"]["time"] = last_tele_data.time - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - ui = new(user, src, ui_key, "telescience_console.tmpl", src.name, 400, 450) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(5) + return data + +/obj/machinery/computer/telescience/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) + if(..()) + return TRUE + if(!telepad || telepad.panel_open) + return TRUE + + switch(action) + if("setrotation") + rotation = CLAMP(text2num(params["val"]), -900, 900) + rotation = round(rotation, 0.01) + + if("setdistance") + distance = CLAMP(text2num(params["val"]), 1, get_max_allowed_distance()) + distance = FLOOR(distance, 1) + + if("setz") + var/new_z = text2num(params["setz"]) + if(new_z in using_map.player_levels) + z_co = new_z + + if("ejectGPS") + if(inserted_gps) + inserted_gps.forceMove(loc) + inserted_gps = null + + if("setMemory") + if(last_target && inserted_gps) + // TODO - What was this even supposed to do?? + //inserted_gps.locked_location = last_target + temp_msg = "Location saved." + else + temp_msg = "ERROR! No data was stored." + + if("send") + sending = 1 + teleport(usr) + + if("receive") + sending = 0 + teleport(usr) + + if("recal") + recalibrate() + sparks() + temp_msg = "NOTICE: Calibration successful." + + if("eject") + eject() + temp_msg = "NOTICE: Bluespace crystals ejected." + else + return FALSE + + return TRUE /obj/machinery/computer/telescience/proc/sparks() if(telepad) @@ -198,7 +253,7 @@ playsound(telepad, 'sound/weapons/flash.ogg', 50, 1) // Wait depending on the time the projectile took to get there teleporting = 1 - temp_msg = "Powering up bluespace crystals.
Please wait." + temp_msg = "Powering up bluespace crystals. Please wait." spawn(spawn_time) // in deciseconds if(!telepad) @@ -218,12 +273,12 @@ if(!A || (A.flags & BLUE_SHIELDED)) telefail() - temp_msg = "ERROR!
Target is shielded from bluespace intersection!" + temp_msg = "ERROR! Target is shielded from bluespace intersection!" return - temp_msg = "Teleport successful.
" + temp_msg = "Teleport successful. " if(teles_left < 10) - temp_msg += "Calibration required soon.
" + temp_msg += "Calibration required soon. " temp_msg += "Data printed below." var/sparks = get_turf(target) @@ -286,11 +341,11 @@ /obj/machinery/computer/telescience/proc/teleport(mob/user) distance = CLAMP(distance, 0, get_max_allowed_distance()) if(rotation == null || distance == null || z_co == null) - temp_msg = "ERROR!
Set a distance, rotation and sector." + temp_msg = "ERROR! Set a distance, rotation and sector." return if(distance <= 0) telefail() - temp_msg = "ERROR!
No distance selected!" + temp_msg = "ERROR! No distance selected!" return if(!(z_co in using_map.player_levels)) telefail() @@ -300,7 +355,7 @@ doteleport(user) else telefail() - temp_msg = "ERROR!
Calibration required." + temp_msg = "ERROR! Calibration required." return return @@ -310,64 +365,6 @@ crystals -= I distance = 0 -/obj/machinery/computer/telescience/Topic(href, href_list) - if(..()) - return - if(!telepad || telepad.panel_open) - updateDialog() - return - - if(href_list["setrotation"]) - var/new_rot = input("Please input desired bearing in degrees.", name, rotation) as num - if(..()) // Check after we input a value, as they could've moved after they entered something - return - rotation = CLAMP(new_rot, -900, 900) - rotation = round(rotation, 0.01) - - if(href_list["setdistance"]) - var/new_pow = input("Please input desired distance in meters.", name, rotation) as num - if(..()) // Check after we input a value, as they could've moved after they entered something - return - distance = CLAMP(new_pow, 1, get_max_allowed_distance()) - distance = FLOOR(distance, 1) - - if(href_list["setz"]) - var/new_z = text2num(href_list["setz"]) - if(new_z in using_map.player_levels) - z_co = new_z - - if(href_list["ejectGPS"]) - if(inserted_gps) - inserted_gps.forceMove(loc) - inserted_gps = null - - if(href_list["setMemory"]) - if(last_target && inserted_gps) - // TODO - What was this even supposed to do?? - //inserted_gps.locked_location = last_target - temp_msg = "Location saved." - else - temp_msg = "ERROR!
No data was stored." - - if(href_list["send"]) - sending = 1 - teleport(usr) - - if(href_list["receive"]) - sending = 0 - teleport(usr) - - if(href_list["recal"]) - recalibrate() - sparks() - temp_msg = "NOTICE:
Calibration successful." - - if(href_list["eject"]) - eject() - temp_msg = "NOTICE:
Bluespace crystals ejected." - - updateDialog() - /obj/machinery/computer/telescience/proc/recalibrate() teles_left = rand(40, 50) distance_off = rand(-4, 4) diff --git a/code/modules/tgui/modules/agentcard.dm b/code/modules/tgui/modules/agentcard.dm new file mode 100644 index 0000000000..7d35a9bc4a --- /dev/null +++ b/code/modules/tgui/modules/agentcard.dm @@ -0,0 +1,135 @@ +/datum/tgui_module/agentcard + name = "Agent Card" + tgui_id = "AgentCard" + +/datum/tgui_module/agentcard/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state) + var/list/data = ..() + + var/obj/item/weapon/card/id/syndicate/S = tgui_host() + if(!istype(S)) + return list() + + var/list/entries = list() + entries += list(list("name" = "Age", "value" = S.age)) + entries += list(list("name" = "Appearance", "value" = "Set")) + entries += list(list("name" = "Assignment", "value" = S.assignment)) + entries += list(list("name" = "Blood Type", "value" = S.blood_type)) + entries += list(list("name" = "DNA Hash", "value" = S.dna_hash)) + entries += list(list("name" = "Fingerprint Hash", "value" = S.fingerprint_hash)) + entries += list(list("name" = "Name", "value" = S.registered_name)) + entries += list(list("name" = "Photo", "value" = "Update")) + entries += list(list("name" = "Sex", "value" = S.sex)) + entries += list(list("name" = "Factory Reset", "value" = "Use With Care")) + data["entries"] = entries + + data["electronic_warfare"] = S.electronic_warfare + + return data + +/datum/tgui_module/agentcard/tgui_status(mob/user, datum/tgui_state/state) + var/obj/item/weapon/card/id/syndicate/S = tgui_host() + if(!istype(S)) + return STATUS_CLOSE + if(user != S.registered_user) + return STATUS_CLOSE + return ..() + +/datum/tgui_module/agentcard/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) + if(..()) + return TRUE + + var/obj/item/weapon/card/id/syndicate/S = tgui_host() + switch(action) + if("electronic_warfare") + S.electronic_warfare = !S.electronic_warfare + to_chat(usr, "Electronic warfare [S.electronic_warfare ? "enabled" : "disabled"].") + . = TRUE + if("age") + var/new_age = input(usr,"What age would you like to put on this card?","Agent Card Age", S.age) as null|num + if(!isnull(new_age) && tgui_status(usr, state) == STATUS_INTERACTIVE) + if(new_age < 0) + S.age = initial(S.age) + else + S.age = new_age + to_chat(usr, "Age has been set to '[S.age]'.") + . = TRUE + if("appearance") + var/datum/card_state/choice = input(usr, "Select the appearance for this card.", "Agent Card Appearance") as null|anything in id_card_states() + if(choice && tgui_status(usr, state) == STATUS_INTERACTIVE) + S.icon_state = choice.icon_state + S.item_state = choice.item_state + to_chat(usr, "Appearance changed to [choice].") + . = TRUE + if("assignment") + var/new_job = sanitize(input(usr,"What assignment would you like to put on this card?\nChanging assignment will not grant or remove any access levels.","Agent Card Assignment", S.assignment) as null|text) + if(!isnull(new_job) && tgui_status(usr, state) == STATUS_INTERACTIVE) + S.assignment = new_job + to_chat(usr, "Occupation changed to '[new_job]'.") + S.update_name() + . = TRUE + if("bloodtype") + var/default = S.blood_type + if(default == initial(S.blood_type) && ishuman(usr)) + var/mob/living/carbon/human/H = usr + if(H.dna) + default = H.dna.b_type + var/new_blood_type = sanitize(input(usr,"What blood type would you like to be written on this card?","Agent Card Blood Type",default) as null|text) + if(!isnull(new_blood_type) && tgui_status(usr, state) == STATUS_INTERACTIVE) + S.blood_type = new_blood_type + to_chat(usr, "Blood type changed to '[new_blood_type]'.") + . = TRUE + if("dnahash") + var/default = S.dna_hash + if(default == initial(S.dna_hash) && ishuman(usr)) + var/mob/living/carbon/human/H = usr + if(H.dna) + default = H.dna.unique_enzymes + var/new_dna_hash = sanitize(input(usr,"What DNA hash would you like to be written on this card?","Agent Card DNA Hash",default) as null|text) + if(!isnull(new_dna_hash) && tgui_status(usr, state) == STATUS_INTERACTIVE) + S.dna_hash = new_dna_hash + to_chat(usr, "DNA hash changed to '[new_dna_hash]'.") + . = TRUE + if("fingerprinthash") + var/default = S.fingerprint_hash + if(default == initial(S.fingerprint_hash) && ishuman(usr)) + var/mob/living/carbon/human/H = usr + if(H.dna) + default = md5(H.dna.uni_identity) + var/new_fingerprint_hash = sanitize(input(usr,"What fingerprint hash would you like to be written on this card?","Agent Card Fingerprint Hash",default) as null|text) + if(!isnull(new_fingerprint_hash) && tgui_status(usr, state) == STATUS_INTERACTIVE) + S.fingerprint_hash = new_fingerprint_hash + to_chat(usr, "Fingerprint hash changed to '[new_fingerprint_hash]'.") + . = TRUE + if("name") + var/new_name = sanitizeName(input(usr,"What name would you like to put on this card?","Agent Card Name", S.registered_name) as null|text) + if(!isnull(new_name) && tgui_status(usr, state) == STATUS_INTERACTIVE) + S.registered_name = new_name + S.update_name() + to_chat(usr, "Name changed to '[new_name]'.") + . = TRUE + if("photo") + S.set_id_photo(usr) + to_chat(usr, "Photo changed.") + . = TRUE + if("sex") + var/new_sex = sanitize(input(usr,"What sex would you like to put on this card?","Agent Card Sex", S.sex) as null|text) + if(!isnull(new_sex) && tgui_status(usr, state) == STATUS_INTERACTIVE) + S.sex = new_sex + to_chat(usr, "Sex changed to '[new_sex]'.") + . = TRUE + if("factoryreset") + if(alert("This will factory reset the card, including access and owner. Continue?", "Factory Reset", "No", "Yes") == "Yes" && tgui_status(usr, state) == STATUS_INTERACTIVE) + S.age = initial(S.age) + S.access = syndicate_access.Copy() + S.assignment = initial(S.assignment) + S.blood_type = initial(S.blood_type) + S.dna_hash = initial(S.dna_hash) + S.electronic_warfare = initial(S.electronic_warfare) + S.fingerprint_hash = initial(S.fingerprint_hash) + S.icon_state = initial(S.icon_state) + S.name = initial(S.name) + S.registered_name = initial(S.registered_name) + S.unset_registered_user() + S.sex = initial(S.sex) + to_chat(usr, "All information has been deleted from \the [src].") + . = TRUE diff --git a/code/modules/tgui/modules/atmos_control.dm b/code/modules/tgui/modules/atmos_control.dm index 83d3db4d1e..4fd477a531 100644 --- a/code/modules/tgui/modules/atmos_control.dm +++ b/code/modules/tgui/modules/atmos_control.dm @@ -34,6 +34,11 @@ ui.set_map_z_level(params["mapZLevel"]) return TRUE +/datum/tgui_module/atmos_control/ui_assets(mob/user) + return list( + get_asset_datum(/datum/asset/simple/nanomaps), + ) + /datum/tgui_module/atmos_control/tgui_interact(mob/user, datum/tgui/ui = null) ui = SStgui.try_update_ui(user, src, ui) if(!ui) diff --git a/code/modules/tgui/modules/crew_manifest.dm b/code/modules/tgui/modules/crew_manifest.dm new file mode 100644 index 0000000000..7c4daf7f2a --- /dev/null +++ b/code/modules/tgui/modules/crew_manifest.dm @@ -0,0 +1,14 @@ +/datum/tgui_module/crew_manifest + name = "Crew Manifest" + tgui_id = "CrewManifest" + +/datum/tgui_module/crew_manifest/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state) + var/list/data = ..() + if(data_core) + data_core.get_manifest_list() + data["manifest"] = PDA_Manifest + return data + +/datum/tgui_module/crew_manifest/robot +/datum/tgui_module/crew_manifest/robot/tgui_state(mob/user) + return GLOB.tgui_self_state \ No newline at end of file diff --git a/code/modules/tgui/modules/crew_monitor.dm b/code/modules/tgui/modules/crew_monitor.dm index 9d4af68652..d24cd3414a 100644 --- a/code/modules/tgui/modules/crew_monitor.dm +++ b/code/modules/tgui/modules/crew_monitor.dm @@ -2,6 +2,11 @@ name = "Crew monitor" tgui_id = "CrewMonitor" +/datum/tgui_module/crew_monitor/ui_assets(mob/user) + return list( + get_asset_datum(/datum/asset/simple/nanomaps), + ) + /datum/tgui_module/crew_monitor/tgui_act(action, params, datum/tgui/ui) if(..()) return TRUE diff --git a/code/modules/tgui/modules/teleporter.dm b/code/modules/tgui/modules/teleporter.dm new file mode 100644 index 0000000000..05529390fe --- /dev/null +++ b/code/modules/tgui/modules/teleporter.dm @@ -0,0 +1,85 @@ +/datum/tgui_module/teleport_control + name = "Teleporter Control" + tgui_id = "Teleporter" + var/locked_name = "Not Locked" + var/obj/item/locked = null + var/obj/machinery/teleport/station/station = null + var/obj/machinery/teleport/hub/hub = null + +/datum/tgui_module/teleport_control/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state) + var/list/data = ..() + + data["locked_name"] = locked_name || "No Target" + data["station_connected"] = !!station + data["hub_connected"] = !!hub + data["calibrated"] = hub?.accurate + data["teleporter_on"] = station?.engaged + + return data + +/datum/tgui_module/teleport_control/tgui_act(action, params, datum/tgui/ui, datum/tgui_state/state) + if(..()) + return TRUE + + switch(action) + if("select_target") + var/list/L = list() + var/list/areaindex = list() + + for(var/obj/item/device/radio/beacon/R in all_beacons) + var/turf/T = get_turf(R) + if(!T) + continue + if(!(T.z in using_map.player_levels)) + continue + var/tmpname = T.loc.name + if(areaindex[tmpname]) + tmpname = "[tmpname] ([++areaindex[tmpname]])" + else + areaindex[tmpname] = 1 + L[tmpname] = R + + for(var/obj/item/weapon/implant/tracking/I in all_tracking_implants) + if(!I.implanted || !ismob(I.loc)) + continue + else + var/mob/M = I.loc + if(M.stat == 2) + if(M.timeofdeath + 6000 < world.time) + continue + var/turf/T = get_turf(M) + if(T) + continue + if(!(T in using_map.station_levels)) + continue + var/tmpname = M.real_name + if(areaindex[tmpname]) + tmpname = "[tmpname] ([++areaindex[tmpname]])" + else + areaindex[tmpname] = 1 + L[tmpname] = I + + var/desc = input("Please select a location to lock in.", "Locking Menu") in L|null + if(!desc) + return FALSE + if(tgui_status(usr, state) != STATUS_INTERACTIVE) + return FALSE + + locked = L[desc] + locked_name = desc + return TRUE + + if("test_fire") + station?.testfire() + return TRUE + + if("toggle_on") + if(!station) + return FALSE + + if(station.engaged) + station.disengage() + else + station.engage() + + return TRUE diff --git a/code/modules/nano/nanomapgen.dm b/code/modules/tgui/nanomapgen.dm similarity index 97% rename from code/modules/nano/nanomapgen.dm rename to code/modules/tgui/nanomapgen.dm index d5a7cfaf69..79c2332901 100644 --- a/code/modules/nano/nanomapgen.dm +++ b/code/modules/tgui/nanomapgen.dm @@ -48,7 +48,7 @@ sleep(3) return NANOMAP_TERMINALERR - var/icon/Tile = icon(file("nano/mapbase1200.png")) + var/icon/Tile = icon('icons/_nanomaps/mapbase1200.png') if (Tile.Width() != NANOMAP_MAX_ICON_DIMENSION || Tile.Height() != NANOMAP_MAX_ICON_DIMENSION) to_world_log("NanoMapGen: ERROR: BASE IMAGE DIMENSIONS ARE NOT [NANOMAP_MAX_ICON_DIMENSION]x[NANOMAP_MAX_ICON_DIMENSION]") sleep(3) diff --git a/code/modules/tgui/states.dm b/code/modules/tgui/states.dm index 111ee9e30b..b2208e4f99 100644 --- a/code/modules/tgui/states.dm +++ b/code/modules/tgui/states.dm @@ -123,3 +123,7 @@ if((TK in mutations) && (get_dist(src, src_object) <= 2)) return STATUS_INTERACTIVE return ..() + +// Topic Extensions for old UIs +/datum/proc/CanUseTopic(var/mob/user, var/datum/tgui_state/state) + return tgui_status(user, state) \ No newline at end of file diff --git a/code/modules/tgui/states/deep_inventory.dm b/code/modules/tgui/states/deep_inventory.dm index 137f262a0e..1441987453 100644 --- a/code/modules/tgui/states/deep_inventory.dm +++ b/code/modules/tgui/states/deep_inventory.dm @@ -10,3 +10,11 @@ GLOBAL_DATUM_INIT(tgui_deep_inventory_state, /datum/tgui_state/deep_inventory_st if(!user.contains(src_object)) return STATUS_CLOSE return user.shared_tgui_interaction(src_object) + +/atom/proc/contains(var/atom/location) + if(!location) + return 0 + if(location == src) + return 1 + + return contains(location.loc) diff --git a/code/modules/tgui/states/default.dm b/code/modules/tgui/states/default.dm index ba8d132e0b..a69295452b 100644 --- a/code/modules/tgui/states/default.dm +++ b/code/modules/tgui/states/default.dm @@ -68,12 +68,12 @@ GLOBAL_DATUM_INIT(tgui_default_state, /datum/tgui_state/default, new) /mob/living/silicon/pai/default_can_use_tgui_topic(src_object) // pAIs can only use themselves and the owner's radio. - if((src_object == src || src_object == radio) && !stat) + if((src_object == src || src_object == radio || src_object == communicator) && !stat) return STATUS_INTERACTIVE else return ..() /mob/observer/dead/default_can_use_tgui_topic() - if(check_rights(R_ADMIN, 0, src)) + if(can_admin_interact()) return STATUS_INTERACTIVE // Admins are more equal return STATUS_UPDATE // Ghosts can view updates diff --git a/code/modules/tgui/tgui.dm b/code/modules/tgui/tgui.dm index 2f928ae6fa..eb128a129b 100644 --- a/code/modules/tgui/tgui.dm +++ b/code/modules/tgui/tgui.dm @@ -114,7 +114,6 @@ closing = TRUE for(var/datum/tgui/child in children) child.close(can_be_suspended, logout) - children.Cut() // If we don't have window_id, open proc did not have the opportunity // to finish, therefore it's safe to skip this whole block. if(window) @@ -126,6 +125,8 @@ src_object.tgui_close(user) SStgui.on_close(src) state = null + if(parent_ui) + parent_ui.children -= src parent_ui = null qdel(src) diff --git a/nano/mapbase1200.png b/icons/_nanomaps/mapbase1200.png similarity index 100% rename from nano/mapbase1200.png rename to icons/_nanomaps/mapbase1200.png diff --git a/nano/images/nanomapBackground.png b/icons/_nanomaps/nanomapBackground.png similarity index 100% rename from nano/images/nanomapBackground.png rename to icons/_nanomaps/nanomapBackground.png diff --git a/nano/images/southern_cross_nanomap_z1.png b/icons/_nanomaps/southern_cross_nanomap_z1.png similarity index 100% rename from nano/images/southern_cross_nanomap_z1.png rename to icons/_nanomaps/southern_cross_nanomap_z1.png diff --git a/nano/images/southern_cross_nanomap_z10.png b/icons/_nanomaps/southern_cross_nanomap_z10.png similarity index 100% rename from nano/images/southern_cross_nanomap_z10.png rename to icons/_nanomaps/southern_cross_nanomap_z10.png diff --git a/nano/images/southern_cross_nanomap_z2.png b/icons/_nanomaps/southern_cross_nanomap_z2.png similarity index 100% rename from nano/images/southern_cross_nanomap_z2.png rename to icons/_nanomaps/southern_cross_nanomap_z2.png diff --git a/nano/images/southern_cross_nanomap_z3.png b/icons/_nanomaps/southern_cross_nanomap_z3.png similarity index 100% rename from nano/images/southern_cross_nanomap_z3.png rename to icons/_nanomaps/southern_cross_nanomap_z3.png diff --git a/nano/images/southern_cross_nanomap_z5.png b/icons/_nanomaps/southern_cross_nanomap_z5.png similarity index 100% rename from nano/images/southern_cross_nanomap_z5.png rename to icons/_nanomaps/southern_cross_nanomap_z5.png diff --git a/nano/images/southern_cross_nanomap_z6.png b/icons/_nanomaps/southern_cross_nanomap_z6.png similarity index 100% rename from nano/images/southern_cross_nanomap_z6.png rename to icons/_nanomaps/southern_cross_nanomap_z6.png diff --git a/nano/images/tether_nanomap_z1.png b/icons/_nanomaps/tether_nanomap_z1.png similarity index 100% rename from nano/images/tether_nanomap_z1.png rename to icons/_nanomaps/tether_nanomap_z1.png diff --git a/nano/images/tether_nanomap_z10.png b/icons/_nanomaps/tether_nanomap_z10.png similarity index 100% rename from nano/images/tether_nanomap_z10.png rename to icons/_nanomaps/tether_nanomap_z10.png diff --git a/nano/images/tether_nanomap_z13.png b/icons/_nanomaps/tether_nanomap_z13.png similarity index 100% rename from nano/images/tether_nanomap_z13.png rename to icons/_nanomaps/tether_nanomap_z13.png diff --git a/nano/images/tether_nanomap_z14.png b/icons/_nanomaps/tether_nanomap_z14.png similarity index 100% rename from nano/images/tether_nanomap_z14.png rename to icons/_nanomaps/tether_nanomap_z14.png diff --git a/nano/images/tether_nanomap_z2.png b/icons/_nanomaps/tether_nanomap_z2.png similarity index 100% rename from nano/images/tether_nanomap_z2.png rename to icons/_nanomaps/tether_nanomap_z2.png diff --git a/nano/images/tether_nanomap_z3.png b/icons/_nanomaps/tether_nanomap_z3.png similarity index 100% rename from nano/images/tether_nanomap_z3.png rename to icons/_nanomaps/tether_nanomap_z3.png diff --git a/nano/images/tether_nanomap_z4.png b/icons/_nanomaps/tether_nanomap_z4.png similarity index 100% rename from nano/images/tether_nanomap_z4.png rename to icons/_nanomaps/tether_nanomap_z4.png diff --git a/nano/images/tether_nanomap_z5.png b/icons/_nanomaps/tether_nanomap_z5.png similarity index 100% rename from nano/images/tether_nanomap_z5.png rename to icons/_nanomaps/tether_nanomap_z5.png diff --git a/nano/images/tether_nanomap_z6.png b/icons/_nanomaps/tether_nanomap_z6.png similarity index 100% rename from nano/images/tether_nanomap_z6.png rename to icons/_nanomaps/tether_nanomap_z6.png diff --git a/nano/images/tether_nanomap_z7.png b/icons/_nanomaps/tether_nanomap_z7.png similarity index 100% rename from nano/images/tether_nanomap_z7.png rename to icons/_nanomaps/tether_nanomap_z7.png diff --git a/nano/images/tether_nanomap_z8.png b/icons/_nanomaps/tether_nanomap_z8.png similarity index 100% rename from nano/images/tether_nanomap_z8.png rename to icons/_nanomaps/tether_nanomap_z8.png diff --git a/nano/images/tether_nanomap_z9.png b/icons/_nanomaps/tether_nanomap_z9.png similarity index 100% rename from nano/images/tether_nanomap_z9.png rename to icons/_nanomaps/tether_nanomap_z9.png diff --git a/maps/offmap_vr/talon/talon.dm b/maps/offmap_vr/talon/talon.dm index b05b7ec13a..b11afb614f 100644 --- a/maps/offmap_vr/talon/talon.dm +++ b/maps/offmap_vr/talon/talon.dm @@ -404,7 +404,7 @@ Once in open space, consider disabling nonessential power-consuming electronics /datum/tgui_module/camera/ntos/talon_ship name = "Talon Ship Camera Monitor" -/datum/nano_module/camera_monitor/talon_ship/New(host) +/datum/tgui_module/camera/ntos/New(host) . = ..(host, list(NETWORK_TALON_SHIP, NETWORK_THUNDER)) /datum/tgui_module/camera/ntos/talon_helmet diff --git a/nano/README.md b/nano/README.md deleted file mode 100644 index 5a3f55425b..0000000000 --- a/nano/README.md +++ /dev/null @@ -1,297 +0,0 @@ - - -- [NanoUI](#nanoui) - - [Introduction](#introduction) - - [Components](#components) - - [`ui_interact()`](#ui_interact) - - [`Topic()`](#topic) - - [Template (doT)](#template-dot) - - [Helpers](#helpers) - - [Link](#link) - - [displayBar](#displayBar) - - [doT](#dot) - - [Styling](#styling) - - [Contributing](#contributing) - - -# NanoUI - -## Introduction - -### Credit goes to Neersighted of /tg/station for the styling and large chunks of content of this README. - -NanoUI is one of the three primary user interface libraries currently in use -on Polaris (browse(), /datum/browser, NanoUI). It is the most complex of the three, -but offers quite a few advantages, most notably in default features. - -NanoUI adds a `ui_interact()` proc to all atoms, which, ideally, should be called -via `interact()`; However, the current standardized layout is `ui_interact()` being -directly called from anywhere in the atom, generally `attack_hand()` or `attack_self()`. -The `ui_interact()` proc should not contain anything but NanoUI data and code. - -Here is a simple example from -[poolcontroller.dm @ ParadiseSS13/Paradise](https://github.com/ParadiseSS13/Paradise/blob/master/code/game/machinery/poolcontroller.dm). - -``` - /obj/machinery/poolcontroller/attack_hand(mob/user) - ui_interact(user) - - /obj/machinery/poolcontroller/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - var/data[0] - - data["currentTemp"] = temperature - data["emagged"] = emagged - data["TempColor"] = temperaturecolor - - ui = SSnano.try_update_ui(user, src, ui_key, ui, data, force_open) - if(!ui) - ui = new(user, src, ui_key, "poolcontroller.tmpl", "Pool Controller Interface", 520, 410) - ui.set_initial_data(data) - ui.open() -``` - - - -## Components - -### `ui_interact()` - -The `ui_interact()` proc is used to open a NanoUI (or update it if already open). -As NanoUI will call this proc to update your UI, you should include the data list -within it. On /tg/station, this is handled via `get_ui_data()`, however, as it would -take quite a long time to convert every single one of the 100~ UI's to using such a method, -it is instead just directly created within `ui_interact()`. - -The parameters for `try_update_ui` and `/datum/nanoui/New()` are documented in -the code [here](https://github.com/PolarisSS13/Polaris/tree/master/code/modules/nano). - -For: -`/datum/nanoui/New(nuser, nsrc_object, nui_key, ntemplate_filename, ntitle = 0, nwidth = 0, nheight = 0, var/atom/nref = null, var/datum/nanoui/master_ui = null, var/datum/topic_state/state = default_state)` -Most of the parameters are fairly self explanatory. - - `nuser` is the person who gets to see the UI window - - `nsrc_obj` is the thing you want to call Topic() on - - `nui_key` should almost always be `main` - - `ntemplate_filename` is the filename with `.tmpl` extension in /nano/templates/ - - `ntitle` is what you want to show at the top of the UI window - - `nwidth` is the width of the new window - - `nheight` is the height of the new window - - `nref` is used for onclose() - - `master_ui` is used for UIs that have multiple children, see code for examples - - And finally, `state`. - -The most interesting parameter here is `state`, which allows the object to choose the -checks that allow the UI to be interacted with. - -The default state (`default_state`) checks that the user is alive, conscious, -and within a few tiles. It allows universal access to silicons. Other states -exist, and may be more appropriate for different interfaces. For example, -`physical_state` requires the user to be nearby, even if they are a silicon. -`inventory_state` checks that the user has the object in their first-level -(not container) inventory, this is suitable for devices such as radios; -`admin_state` checks that the user is an admin (good for admin tools). - -``` - /obj/item/the/thing/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, force_open = 0) - var/data[0] - - ui = SSnano.try_update_ui(user, src, ui_key, ui, data, force_open = force_open) - if(!ui) - ui = new(user, src, ui_key, "template_name_here.tmpl", title, width, height) - ui.set_initial_data(data) - ui.open() -``` - -### `Topic()` - -`Topic()` handles input from the UI. Typically you will recieve some data from -a button press, or pop up a input dialog to take a numerical value from the -user. Sanity checking is useful here, as `Topic()` is trivial to spoof with -arbitrary data. - -The `Topic()` interface is just the same as with more conventional, -stringbuilder-based UIs, and this needs little explanation. - -``` - /obj/item/weapon/tank/Topic(href, href_list) - if(..()) - return 1 - - if(href_list["dist_p"]) - if(href_list["dist_p"] == "custom") - var/custom = input(usr, "What rate do you set the regulator to? The dial reads from 0 to [TANK_MAX_RELEASE_PRESSURE].") as null|num - if(isnum(custom)) - href_list["dist_p"] = custom - .() - else if(href_list["dist_p"] == "reset") - distribute_pressure = TANK_DEFAULT_RELEASE_PRESSURE - else if(href_list["dist_p"] == "min") - distribute_pressure = TANK_MIN_RELEASE_PRESSURE - else if(href_list["dist_p"] == "max") - distribute_pressure = TANK_MAX_RELEASE_PRESSURE - else - distribute_pressure = text2num(href_list["dist_p"]) - distribute_pressure = min(max(round(distribute_pressure), TANK_MIN_RELEASE_PRESSURE), TANK_MAX_RELEASE_PRESSURE) - if(href_list["stat"]) - if(istype(loc,/mob/living/carbon)) - var/mob/living/carbon/location = loc - if(location.internal == src) - location.internal = null - location.internals.icon_state = "internal0" - to_chat(usr, "You close the tank release valve.") - if(location.internals) - location.internals.icon_state = "internal0" - else - if(location.wear_mask && (location.wear_mask.flags & MASKINTERNALS)) - location.internal = src - to_chat(usr, "You open \the [src] valve.") - if(location.internals) - location.internals.icon_state = "internal1" - else - to_chat(usr, "You need something to connect to \the [src]!") -``` - -### Template (doT) - -NanoUI templates are written in a customized version of -[doT](https://olado.github.io/doT/index.html), -a Javascript template engine. Data is accessed from the `data` object, -configuration (not used in pratice) from the `config` object, and template -helpers are accessed from the `helper` object. - -It is worth explaining that Polaris's version of doT uses custom syntax -for the templates. The `?` operator is split into `if`, `else if parameter`, and `else`, -instead of `?`, `?? paramater`, `??`, and the `=` operator is replaced with `:`. Refer -to the chart below for a full comparison. - -#### Helpers - -##### Link - -`{{:helpers.link(text, icon, {'parameter': true}, status, class, id)}}` - -Used to create a link (button), which will pass its parameters to `Topic()`. - -* Text: The text content of the link/button -* Icon: The icon shown to the left of the link (http://fontawesome.io/) -* Parameters: The values to be passed to `Topic()`'s `href_list`. -* Status: `null` for clickable, a class for selected/unclickable. -* Class: Styling to apply to the link. -* ID: Sets the element ID. - -Status and Class have almost the same effect. However, changing a link's status -from `null` to something else makes it unclickable, while setting a custom Class -does not. - -Ternary operators are often used to avoid writing many `if` statements. -For example, depending on if a value in `data` is true or false we can set a -button to clickable or selected: - -`{{:helper.link('Close', 'lock', {'stat': 1}, data.valveOpen ? null : 'selected')}}` - -Available classes/statuses are: - -* null (normal) -* selected -* disabled -* yellowButton -* redButton -* linkDanger - -##### displayBar - -`{{:helpers.displayBar(value, min, max, class, text)}}` - -Used to create a bar, to display a numerical value visually. Min and Max default -to 0 and 100, but you can change them to avoid doing your own percent calculations. - -* Value: Defaults to a percentage but can be a straight number if Min/Max are set -* Min: The minimum value (left hand side) of the bar -* Max: The maximum value (right hand side) of the bar -* Class: The color of the bar (null/normal, good, average, bad) -* Text: The text label for the data contained in the bar (often just number form) - -As with buttons, ternary operators are quite useful: - -`{{:helper.bar(data.tankPressure, 0, 1013, (data.tankPressure > 200) ? 'good' : ((data.tankPressure > 100) ? 'average' : 'bad'))}}` - - -#### doT - -doT is a simple template language, with control statements mixed in with -regular HTML and interpolation expressions. - -However, Polaris uses a custom version with a different syntax. Refer -to the chart below for the differences. - -Operator | doT | equiv | -|-----------|------------|-------------------| -|Conditional| ? | if | -| | ?? | else | -| | ?? (param) | else if(param) | -|Interpolate| = | : | -|^ + Encode | ! | > | -|Evaluation | # | # | -|Defines | ## # | ## # | -|Iteration | ~ (param) | for (param) | - -Here is a simple example from tanks, checking if a variable is true: - -``` - {{if data.maskConnected}} - The regulator is connected to a mask. - {{else if}} - The regulator is not connected to a mask. - {{/if}} -``` - -The doT tutorial is [here](https://olado.github.io/doT/tutorial.html). - -__Print Tag__ -- The print tag outputs the given expression as text to the UI. - -`{{:data.variable}}` -`{{:functioncall()}}` - -(with escape): - -`{{>expression }}` - - -__If Tag__ -- The if tag displays content conditionally based on the provided expression being true. -- When combined with the else tag the if tag can also show content if the provided expression is false. -- The else tag can optionally have an expression provided (e.g. "`{{else expression2}}`"), giving it "elseif" functionality. - -`{{if expression}} {{/if}}` -`{{if expression}} {{else}} {{/if}}` -`{{if expression1}} {{else expression2}} {{/if}}` - -__For Tag__ -- Loop through entries in an array; it can be associative (with keys) or numerical indexed, but you have to use some special syntax for assocative lists. -- Each time the `for` tag iterates though the array it sets a variable (default "value") to the data of the current entry (another variable, default "index", contains the index). An example of this is using the print tag to print the contents (e.g. `{{:value.key1}}` and `{{:value.key2}}`). -- If combined with an `empty` tag the for tag can display content when the array is empty. - -Indexed: -`{{for array}} {{/for}}` -`{{for array}} {{empty}} {{/for}}` - -Associative: -`{{for object:key:index}} {{/for}}` - - -__Inclusion Tag__ -- Include the contents of another template which has been added to the ui. -`{{#def.atmosphericScan}}` - -- You first must have added a template to the ui server side in your DM code: -`ui.add_template("atmosphericScan", "atmospheric_scan.tmpl")` - -- Then you can reference it in the main template. The tag will be replaced by the contents of the named template. All tags in the named template are evaluated as normal. - -#### Styling -/tg/station has standardized styling, with specific article tags, and headers, and sections. -However, as the templates are already horrifying unstandardized, Polaris does not have any -particular styling standards. - -The only real requirement is that it, A. Looks alrightish, and B. Functions properly. Try -to avoid snowflaking anything into the main CSS file, please. diff --git a/nano/Update BYOND Cache.py b/nano/Update BYOND Cache.py deleted file mode 100644 index 032c42ff1b..0000000000 --- a/nano/Update BYOND Cache.py +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/python3 -# Setup -import os, json, shutil, glob, platform - -if(platform.system() != "Windows"): - print("Error: This script doesn't work on anything but Windows. How are you even planning to develop BYOND off windows?") - exit() - -cdir = (os.getcwd()) -if(cdir[-4:] != "nano"): - print("This script must be run from the nano directory.") - exit() - -def find_cache(): - target = os.path.join(os.path.expanduser("~"), "Documents", "BYOND", "cache") - for root, dirs, files in os.walk(target): - if "nano_templates_bundle.js" in files: - return root - -cache = find_cache() -if cache == None: - print("Failed to find BYOND Cache.") - exit() - -# Send all of the random files to the cache -def send_to_cache(arrayOfFiles): - for file in arrayOfFiles: - target = os.path.join(cache, os.path.split(file)[1]) - shutil.copyfile(file, target) - -send_to_cache([os.path.join(cdir, "css", f) for f in os.listdir(os.path.join(cdir, "css")) if os.path.isfile(os.path.join(cdir, "css", f))]) -send_to_cache([os.path.join(cdir, "images", f) for f in os.listdir(os.path.join(cdir, "images")) if os.path.isfile(os.path.join(cdir, "images", f))]) -send_to_cache([os.path.join(cdir, "js", f) for f in os.listdir(os.path.join(cdir, "js")) if os.path.isfile(os.path.join(cdir, "js", f))]) - -# Handle creating the tmpl bundle -arrOfFiles = glob.glob(os.path.join(cdir, "templates", "*.tmpl")) - -tmpl_bundle_header = "function nanouiTemplateBundle(){return " -tmpl_bundle_footer = ";}" - -big_json_array = {} - -for file in arrOfFiles: - tmpl_name = os.path.split(file)[1] - with open(file, 'r') as tmpl: - big_json_array[tmpl_name] = tmpl.read() - -tmpl_bundle = tmpl_bundle_header + json.dumps(big_json_array) + tmpl_bundle_footer - -# Send the tmpl bundle to the cache -with open(os.path.join(cache, "nano_templates_bundle.js"), "w") as templateBundleFile: - templateBundleFile.write(tmpl_bundle) - templateBundleFile.close() \ No newline at end of file diff --git a/nano/css/icons.css b/nano/css/icons.css deleted file mode 100644 index 23d4ba0606..0000000000 --- a/nano/css/icons.css +++ /dev/null @@ -1,378 +0,0 @@ -/* Icons -----------------------------------*/ - -.icon24 -{ - width: 24px; - height: 24px; -} - -.icon24.uiStatusGood -{ - background: url(uiIcons24.png) 0 0 no-repeat; -} - -.icon24.uiStatusAverage -{ - background: url(uiIcons24.png) 0 -24px no-repeat; -} - -.icon24.uiStatusBad -{ - background: url(uiIcons24.png) 0 -48px no-repeat; -} - -/* states and images */ -.uiIcon16 { - float: left; - width: 16px; - height: 16px; - margin: 2px 2px 0 2px; - background-image: url(uiIcons16.png); -} - -.uiLinkPendingIcon { - display: none; - float: left; - width: 16px; - height: 16px; - margin: 2px 2px 0 2px; - background-image: url(uiLinkPendingIcon.gif); -} - -.linkPending .uiIcon16 { - display: none; -} - -.linkPending .uiLinkPendingIcon { - display: block; -} - -/* positioning */ -.uiIcon16.icon-blank { background-position: 16px 16px; } - -.uiIcon16.icon-carat-1-n { background-position: 0 0; } -.uiIcon16.icon-carat-1-ne { background-position: -16px 0; } -.uiIcon16.icon-carat-1-e { background-position: -32px 0; } -.uiIcon16.icon-carat-1-se { background-position: -48px 0; } -.uiIcon16.icon-carat-1-s { background-position: -64px 0; } -.uiIcon16.icon-carat-1-sw { background-position: -80px 0; } -.uiIcon16.icon-carat-1-w { background-position: -96px 0; } -.uiIcon16.icon-carat-1-nw { background-position: -112px 0; } -.uiIcon16.icon-carat-2-n-s { background-position: -128px 0; } -.uiIcon16.icon-carat-2-e-w { background-position: -144px 0; } - -.uiIcon16.icon-triangle-1-n { background-position: 0 -16px; } -.uiIcon16.icon-triangle-1-ne { background-position: -16px -16px; } -.uiIcon16.icon-triangle-1-e { background-position: -32px -16px; } -.uiIcon16.icon-triangle-1-se { background-position: -48px -16px; } -.uiIcon16.icon-triangle-1-s { background-position: -64px -16px; } -.uiIcon16.icon-triangle-1-sw { background-position: -80px -16px; } -.uiIcon16.icon-triangle-1-w { background-position: -96px -16px; } -.uiIcon16.icon-triangle-1-nw { background-position: -112px -16px; } -.uiIcon16.icon-triangle-2-n-s { background-position: -128px -16px; } -.uiIcon16.icon-triangle-2-e-w { background-position: -144px -16px; } - -.uiIcon16.icon-arrow-1-n { background-position: 0 -32px; } -.uiIcon16.icon-arrow-1-ne { background-position: -16px -32px; } -.uiIcon16.icon-arrow-1-e { background-position: -32px -32px; } -.uiIcon16.icon-arrow-1-se { background-position: -48px -32px; } -.uiIcon16.icon-arrow-1-s { background-position: -64px -32px; } -.uiIcon16.icon-arrow-1-sw { background-position: -80px -32px; } -.uiIcon16.icon-arrow-1-w { background-position: -96px -32px; } -.uiIcon16.icon-arrow-1-nw { background-position: -112px -32px; } -.uiIcon16.icon-arrow-2-n-s { background-position: -128px -32px; } -.uiIcon16.icon-arrow-2-ne-sw { background-position: -144px -32px; } -.uiIcon16.icon-arrow-2-e-w { background-position: -160px -32px; } -.uiIcon16.icon-arrow-2-se-nw { background-position: -176px -32px; } - -.uiIcon16.icon-arrowstop-1-n { background-position: -192px -32px; } -.uiIcon16.icon-arrowstop-1-e { background-position: -208px -32px; } -.uiIcon16.icon-arrowstop-1-s { background-position: -224px -32px; } -.uiIcon16.icon-arrowstop-1-w { background-position: -240px -32px; } - -.uiIcon16.icon-arrowthick-1-n { background-position: 0 -48px; } -.uiIcon16.icon-arrowthick-1-ne { background-position: -16px -48px; } -.uiIcon16.icon-arrowthick-1-e { background-position: -32px -48px; } -.uiIcon16.icon-arrowthick-1-se { background-position: -48px -48px; } -.uiIcon16.icon-arrowthick-1-s { background-position: -64px -48px; } -.uiIcon16.icon-arrowthick-1-sw { background-position: -80px -48px; } -.uiIcon16.icon-arrowthick-1-w { background-position: -96px -48px; } -.uiIcon16.icon-arrowthick-1-nw { background-position: -112px -48px; } -.uiIcon16.icon-arrowthick-2-n-s { background-position: -128px -48px; } -.uiIcon16.icon-arrowthick-2-ne-sw { background-position: -144px -48px; } -.uiIcon16.icon-arrowthick-2-e-w { background-position: -160px -48px; } -.uiIcon16.icon-arrowthick-2-se-nw { background-position: -176px -48px; } - -.uiIcon16.icon-arrowthickstop-1-n { background-position: -192px -48px; } -.uiIcon16.icon-arrowthickstop-1-e { background-position: -208px -48px; } -.uiIcon16.icon-arrowthickstop-1-s { background-position: -224px -48px; } -.uiIcon16.icon-arrowthickstop-1-w { background-position: -240px -48px; } - -.uiIcon16.icon-arrowreturnthick-1-w { background-position: 0 -64px; } -.uiIcon16.icon-arrowreturnthick-1-n { background-position: -16px -64px; } -.uiIcon16.icon-arrowreturnthick-1-e { background-position: -32px -64px; } -.uiIcon16.icon-arrowreturnthick-1-s { background-position: -48px -64px; } - -.uiIcon16.icon-arrowreturn-1-w { background-position: -64px -64px; } -.uiIcon16.icon-arrowreturn-1-n { background-position: -80px -64px; } -.uiIcon16.icon-arrowreturn-1-e { background-position: -96px -64px; } -.uiIcon16.icon-arrowreturn-1-s { background-position: -112px -64px; } -.uiIcon16.icon-arrowrefresh-1-w { background-position: -128px -64px; } -.uiIcon16.icon-arrowrefresh-1-n { background-position: -144px -64px; } -.uiIcon16.icon-arrowrefresh-1-e { background-position: -160px -64px; } -.uiIcon16.icon-arrowrefresh-1-s { background-position: -176px -64px; } - -.uiIcon16.icon-arrow-4 { background-position: 0 -80px; } -.uiIcon16.icon-arrow-4-diag { background-position: -16px -80px; } -.uiIcon16.icon-extlink { background-position: -32px -80px; } -.uiIcon16.icon-newwin { background-position: -48px -80px; } -.uiIcon16.icon-refresh { background-position: -64px -80px; } -.uiIcon16.icon-shuffle { background-position: -80px -80px; } -.uiIcon16.icon-transfer-e-w { background-position: -96px -80px; } -.uiIcon16.icon-transferthick-e-w { background-position: -112px -80px; } -.uiIcon16.icon-radiation { background-position: -128px -80px; } -.uiIcon16.icon-folder-collapsed { background-position: 0 -96px; } -.uiIcon16.icon-folder-open { background-position: -16px -96px; } -.uiIcon16.icon-document { background-position: -32px -96px; } -.uiIcon16.icon-document-b { background-position: -48px -96px; } -.uiIcon16.icon-note { background-position: -64px -96px; } -.uiIcon16.icon-mail-closed { background-position: -80px -96px; } -.uiIcon16.icon-mail-open { background-position: -96px -96px; } -.uiIcon16.icon-suitcase { background-position: -112px -96px; } -.uiIcon16.icon-comment { background-position: -128px -96px; } -.uiIcon16.icon-person { background-position: -144px -96px; } -.uiIcon16.icon-print { background-position: -160px -96px; } -.uiIcon16.icon-trash { background-position: -176px -96px; } -.uiIcon16.icon-locked { background-position: -192px -96px; } -.uiIcon16.icon-unlocked { background-position: -208px -96px; } -.uiIcon16.icon-bookmark { background-position: -224px -96px; } -.uiIcon16.icon-tag { background-position: -240px -96px; } -.uiIcon16.icon-home { background-position: 0 -112px; } -.uiIcon16.icon-flag { background-position: -16px -112px; } -.uiIcon16.icon-calendar { background-position: -32px -112px; } -.uiIcon16.icon-cart { background-position: -48px -112px; } -.uiIcon16.icon-pencil { background-position: -64px -112px; } -.uiIcon16.icon-clock { background-position: -80px -112px; } -.uiIcon16.icon-disk { background-position: -96px -112px; } -.uiIcon16.icon-calculator { background-position: -112px -112px; } -.uiIcon16.icon-zoomin { background-position: -128px -112px; } -.uiIcon16.icon-zoomout { background-position: -144px -112px; } -.uiIcon16.icon-search { background-position: -160px -112px; } -.uiIcon16.icon-wrench { background-position: -176px -112px; } -.uiIcon16.icon-gear { background-position: -192px -112px; } -.uiIcon16.icon-heart { background-position: -208px -112px; } -.uiIcon16.icon-star { background-position: -224px -112px; } -.uiIcon16.icon-link { background-position: -240px -112px; } -.uiIcon16.icon-cancel { background-position: 0 -128px; } -.uiIcon16.icon-plus { background-position: -16px -128px; } -.uiIcon16.icon-plusthick { background-position: -32px -128px; } -.uiIcon16.icon-minus { background-position: -48px -128px; } -.uiIcon16.icon-minusthick { background-position: -64px -128px; } -.uiIcon16.icon-close { background-position: -80px -128px; } -.uiIcon16.icon-closethick { background-position: -96px -128px; } -.uiIcon16.icon-key { background-position: -112px -128px; } -.uiIcon16.icon-lightbulb { background-position: -128px -128px; } -.uiIcon16.icon-scissors { background-position: -144px -128px; } -.uiIcon16.icon-clipboard { background-position: -160px -128px; } -.uiIcon16.icon-copy { background-position: -176px -128px; } -.uiIcon16.icon-contact { background-position: -192px -128px; } -.uiIcon16.icon-image { background-position: -208px -128px; } -.uiIcon16.icon-video { background-position: -224px -128px; } -.uiIcon16.icon-script { background-position: -240px -128px; } -.uiIcon16.icon-alert { background-position: 0 -144px; } -.uiIcon16.icon-alert-red { background-image: url(uiIcons16Red.png); background-position: 0 -144px; } -.uiIcon16.icon-info { background-position: -16px -144px; } -.uiIcon16.icon-notice { background-position: -32px -144px; } -.uiIcon16.icon-help { background-position: -48px -144px; } -.uiIcon16.icon-check { background-position: -64px -144px; } -.uiIcon16.icon-bullet { background-position: -80px -144px; } -.uiIcon16.icon-radio-on { background-position: -96px -144px; } -.uiIcon16.icon-radio-off { background-position: -112px -144px; } -.uiIcon16.icon-pin-w { background-position: -128px -144px; } -.uiIcon16.icon-pin-s { background-position: -144px -144px; } -.uiIcon16.icon-phone { background-position: -160px -144px; } -.uiIcon16.icon-list { background-position: -176px -144px; } -.uiIcon16.icon-syringe { background-position: -192px -144px; } -.uiIcon16.icon-play { background-position: 0 -160px; } -.uiIcon16.icon-pause { background-position: -16px -160px; } -.uiIcon16.icon-seek-next { background-position: -32px -160px; } -.uiIcon16.icon-seek-prev { background-position: -48px -160px; } -.uiIcon16.icon-seek-end { background-position: -64px -160px; } -.uiIcon16.icon-seek-start { background-position: -80px -160px; } - -/* uiIcon-seek-first is deprecated, use uiIcon-seek-start instead */ -.uiIcon16.icon-seek-first { background-position: -80px -160px; } -.uiIcon16.icon-stop { background-position: -96px -160px; } -.uiIcon16.icon-eject { background-position: -112px -160px; } -.uiIcon16.icon-volume-off { background-position: -128px -160px; } -.uiIcon16.icon-volume-on { background-position: -144px -160px; } -.uiIcon16.icon-power { background-position: 0 -176px; } -.uiIcon16.icon-signal-diag { background-position: -16px -176px; } -.uiIcon16.icon-signal { background-position: -32px -176px; } -.uiIcon16.icon-signal-green { background-image: url(uiIcons16Green.png); background-position: -32px -176px; } - -.uiIcon16.icon-battery-0 { background-position: -48px -176px; } -.uiIcon16.icon-battery-1 { background-position: -64px -176px; } -.uiIcon16.icon-battery-2 { background-position: -80px -176px; } -.uiIcon16.icon-battery-3 { background-position: -96px -176px; } - -.uiIcon16.icon-circle-plus { background-position: 0 -192px; } -.uiIcon16.icon-circle-minus { background-position: -16px -192px; } -.uiIcon16.icon-circle-close { background-position: -32px -192px; } -.uiIcon16.icon-circle-triangle-e { background-position: -48px -192px; } -.uiIcon16.icon-circle-triangle-s { background-position: -64px -192px; } -.uiIcon16.icon-circle-triangle-w { background-position: -80px -192px; } -.uiIcon16.icon-circle-triangle-n { background-position: -96px -192px; } -.uiIcon16.icon-circle-arrow-e { background-position: -112px -192px; } -.uiIcon16.icon-circle-arrow-s { background-position: -128px -192px; } -.uiIcon16.icon-circle-arrow-w { background-position: -144px -192px; } -.uiIcon16.icon-circle-arrow-n { background-position: -160px -192px; } -.uiIcon16.icon-circle-zoomin { background-position: -176px -192px; } -.uiIcon16.icon-circle-zoomout { background-position: -192px -192px; } -.uiIcon16.icon-circle-check { background-position: -208px -192px; } - -.uiIcon16.icon-circlesmall-plus { background-position: 0 -208px; } -.uiIcon16.icon-circlesmall-minus { background-position: -16px -208px; } -.uiIcon16.icon-circlesmall-close { background-position: -32px -208px; } - -.uiIcon16.icon-squaresmall-plus { background-position: -48px -208px; } -.uiIcon16.icon-squaresmall-minus { background-position: -64px -208px; } -.uiIcon16.icon-squaresmall-close { background-position: -80px -208px; } - -.uiIcon16.icon-grip-dotted-vertical { background-position: 0 -224px; } -.uiIcon16.icon-grip-dotted-horizontal { background-position: -16px -224px; } -.uiIcon16.icon-grip-solid-vertical { background-position: -32px -224px; } -.uiIcon16.icon-grip-solid-horizontal { background-position: -48px -224px; } -.uiIcon16.icon-gripsmall-diagonal-se { background-position: -64px -224px; } -.uiIcon16.icon-grip-diagonal-se { background-position: -80px -224px; } - -.uiIcon16.icon-batt_full { background-image: url(c_max.gif); background-position: 0px 0px } -.uiIcon16.icon-batt_disc { background-image: url(c_discharging.gif); background-position: 0px 0px } -.uiIcon16.icon-batt_chrg { background-image: url(c_charging.gif); background-position: 0px 0px } - -/*yes, defining these all like this is awful, but unless the javascript for icon handling is sorted out this will have to do*/ -.uiIcon16.icon-empty64 { background-image: url(uiIcons64.png); background-position: 0 0; width: 64px; height: 64px; } -.uiIcon16.icon-phone64 { background-image: url(uiIcons64.png); background-position: -64px 0; width: 64px; height: 64px; } -.uiIcon16.icon-comment64 { background-image: url(uiIcons64.png); background-position: -128px 0; width: 64px; height: 64px; } -.uiIcon16.icon-list64 { background-image: url(uiIcons64.png); background-position: -192px 0; width: 64px; height: 64px; } -.uiIcon16.icon-gear64 { background-image: url(uiIcons64.png); background-position: -256px 0; width: 64px; height: 64px; } -.uiIcon16.icon-person64 { background-image: url(uiIcons64.png); background-position: -320px 0; width: 64px; height: 64px; } -.uiIcon16.icon-newspaper64 { background-image: url(uiIcons64.png); background-position: 0 -64px; width: 64px; height: 64px; } -.uiIcon16.icon-note64 { background-image: url(uiIcons64.png); background-position: -64px -64px; width: 64px; height: 64px; } -.uiIcon16.icon-close64 { background-image: url(uiIcons64.png); background-position: -128px -64px; width: 64px; height: 64px; } -.uiIcon16.icon-sun64 { background-image: url(uiIcons64.png); background-position: -192px -64px; width: 64px; height: 64px; } -.uiIcon16.icon-external64 { background-image: url(uiIcons64.png); background-position: -256px -64px; width: 64px; height: 64px; } - -.uiIcon16.icon-pill { background-image: url(pills32.png); width: 32px; height: 32px;} -.uiIcon16.icon-pill.pill1 { background-position: -64px -96px; } -.uiIcon16.icon-pill.pill2 { background-position: -64px -96px; } -.uiIcon16.icon-pill.pill3 { background-position: -96px -32px; } -.uiIcon16.icon-pill.pill4 { background-position: -96px -32px; } -.uiIcon16.icon-pill.pill5 { background-position: 0 0; } -.uiIcon16.icon-pill.pill6 { background-position: -32px 0; } -.uiIcon16.icon-pill.pill7 { background-position: -64px 0; } -.uiIcon16.icon-pill.pill8 { background-position: -96px 0; } -.uiIcon16.icon-pill.pill9 { background-position: -128px 0; } -.uiIcon16.icon-pill.pill10 { background-position: 0 -32px; } -.uiIcon16.icon-pill.pill11 { background-position: -32px -32px; } -.uiIcon16.icon-pill.pill12 { background-position: -64px -32px; } -.uiIcon16.icon-pill.pill13 { background-position: -96px -32px; } -.uiIcon16.icon-pill.pill14 { background-position: -128px -32px; } -.uiIcon16.icon-pill.pill15 { background-position: 0 -64px; } -.uiIcon16.icon-pill.pill16 { background-position: -32px -64px; } -.uiIcon16.icon-pill.pill17 { background-position: -64px -64px; } -.uiIcon16.icon-pill.pill18 { background-position: -96px -64px; } -.uiIcon16.icon-pill.pill19 { background-position: -128px -64px; } -.uiIcon16.icon-pill.pill20 { background-position: 0 -96px; } -.uiIcon16.icon-pill.pill21 { background-position: -32px -96px; } -.uiIcon16.icon-pill.pill22 { background-position: -64px -96px; } -.uiIcon16.icon-pill.pill23 { background-position: -96px -96px; } -.uiIcon16.icon-pill.pill24 { background-position: -128px -96px; } -.uiIcon16.icon-pill.bottle1 { background-position: 0 -128px; } -.uiIcon16.icon-pill.bottle2 { background-position: -32px -128px; } -.uiIcon16.icon-pill.bottle3 { background-position: -64px -128px; } -.uiIcon16.icon-pill.bottle4 { background-position: -96px -128px; } - -.mapIcon16 { - position: absolute; - width: 16px; - height: 16px; - background-image: url(uiIcons16Green.png); - background-position: -144px -96px; - background-repeat: no-repeat; - zoom: 0.125; - margin-left: -1px; - /*margin-bottom: -1px;*/ -} -.mapIcon16.dead { - background-image: url(uiIcons16Red.png); -} - -/* Command Positions */ -.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; -} - -/* Engineering Positions */ -.mapIcon16.rank-stationengineer { - background-position: -176px -112px; -} -.mapIcon16.rank-atmospherictechnician { - background-position: -176px -112px; -} - -/* Medical Positions */ -.mapIcon16.rank-medicaldoctor { - background-position: -32px -128px; -} -.mapIcon16.rank-geneticist { - background-position: -32px -128px; -} -.mapIcon16.rank-psychiatrist { - background-position: -32px -128px; -} -.mapIcon16.rank-chemist { - background-position: -32px -128px; -} - -/* Science Positions */ -.mapIcon16.rank-scientist { - background-position: -128px -128px; -} -.mapIcon16.rank-geneticist { - background-position: -128px -128px; -} -.mapIcon16.rank-roboticist { - background-position: -128px -128px; -} -.mapIcon16.rank-xenobiologist { - background-position: -128px -128px; -} - -/* Security Positions */ -.mapIcon16.rank-warden { - background-position: -112px -128px; -} -.mapIcon16.rank-detective { - background-position: -112px -128px; -} -.mapIcon16.rank-securityofficer { - background-position: -112px -128px; -} - diff --git a/nano/css/layout_basic.css b/nano/css/layout_basic.css deleted file mode 100644 index 30a75490f3..0000000000 --- a/nano/css/layout_basic.css +++ /dev/null @@ -1,21 +0,0 @@ -body { - background: #272727 url(uiBasicBackground.png) 50% 0 repeat-x; -} - -#uiContent { - clear: both; - padding: 8px; -} - -#uiLoadingNotice { - position: relative; - background: url(uiNoticeBackground.jpg) 50% 50%; - color: #000000; - font-size: 14px; - font-style: italic; - font-weight: bold; - padding: 3px 4px 3px 4px; - margin: 4px 0 4px 0; -} - - diff --git a/nano/css/layout_default.css b/nano/css/layout_default.css deleted file mode 100644 index 47002ef5d5..0000000000 --- a/nano/css/layout_default.css +++ /dev/null @@ -1,128 +0,0 @@ -body { - background: #272727 url(uiBackground.png) 50% 0 repeat-x; -} - -#uiWrapper { - width: 100%; - height: 100%; - -ms-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(uiTitleFluff.png) 50% 50% no-repeat; -} - -#uiStatusIcon { - position: absolute; - top: 4px; - left: 12px; - width: 24px; - height: 24px; -} - -#uiMapWrapper { - clear: both; - padding: 8px; -} - -#uiMapHeader { - position: relative; - clear: both; -} - -#uiMapContainer { - position: relative; - width: 100%; - height: 550px; - overflow: hidden; - border: 1px solid #40628a; - background: url(nanomapBackground.png); -} - -#uiMap { - position: absolute; - top: 50%; - left: 50%; - margin: -280px 0 0 -280px; /* VOREStation Edit - Tether map is small */ - width: 140px; /* VOREStation Edit - Tether map is small */ - height: 140px; /* VOREStation Edit - Tether map is small */ - overflow: hidden; - zoom: 4; -} - -#uiMapImage { - position: absolute; - bottom: 1px; - left: 1px; - width: 140px; /* VOREStation Edit - Tether map is small */ - height: 140px; /* VOREStation Edit - Tether map is small */ -} - -#uiMapContent { - position: absolute; - bottom: 0px; - left: 0px; - width: 140px; /* VOREStation Edit - Tether map is small */ - height: 140px; /* VOREStation Edit - Tether map is small */ -} - -#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: 9999; -} - -#uiLoadingNotice { - position: relative; - background: url(uiNoticeBackground.jpg) 50% 50%; - color: #000000; - font-size: 14px; - font-style: italic; - font-weight: bold; - padding: 3px 4px 3px 4px; - margin: 4px 0 4px 0; -} - - diff --git a/nano/css/shared.css b/nano/css/shared.css deleted file mode 100644 index 3517402e2a..0000000000 --- a/nano/css/shared.css +++ /dev/null @@ -1,803 +0,0 @@ -body { - padding: 0; - margin: 0; - font-size: 12px; - color: #ffffff; - line-height: 170%; - font-family: Verdana, Geneva, sans-serif; - background: #272727; -} - -#uiNoScript { - position: fixed; - top: 50%; - left: 50%; - margin: -60px 0 0 -150px; - width: 280px; - height: 120px; - background: #ffffff; - border: 2px solid #ff0000; - color: #000000; - font-size: 10px; - font-weight: bold; - z-index: 9999; - padding: 0px 10px; - text-align: center; -} - -hr { - background-color: #40628a; - height: 1px; -} - -.link, .linkOn, .linkOff, .selected, .disabled, .yellowButton, .redButton { - float: left; - min-width: 15px; - height: 16px; - text-align: center; - color: #ffffff; - text-decoration: none; - background: #40628a; - border: 1px solid #161616; - padding: 0px 4px 4px 4px; - margin: 0 2px 2px 0; - cursor: default; - white-space: nowrap; -} - -.link32 { - float: left; - min-width: 15px; - max-width: 31px; - height: 31px; - text-align: center; - text-decoration: none; - background: #40628a; - border: 1px solid #161616; - margin: 0 2px 2px 0; - cursor: default; -} - -.hasIcon { - padding: 0px 4px 4px 0px; -} - -a:hover, .zoomLink:hover, .linkActive:hover { - background: #507aac; -} - -.linkPending, .linkPending:hover { - color: #ffffff; - background: #507aac; -} - -a.white, a.white:link, a.white:visited, a.white:active { - color: #40628a; - text-decoration: none; - background: #ffffff; - border: 1px solid #161616; - padding: 1px 4px 1px 4px; - margin: 0 2px 0 0; - cursor: default; -} - -a.white:hover { - color: #ffffff; - background: #40628a; -} - -.hidden { - display: none; -} - -.linkOn, a.linkOn:link, a.linkOn:visited, a.linkOn:active, a.linkOn:hover, .selected, a.selected:link, a.selected:visited, a.selected:active, a.selected:hover { - color: #ffffff; - background: #2f943c; -} - -.linkOff, a.linkOff:link, a.linkOff:visited, a.linkOff:active, a.linkOff:hover, .disabled, a.disabled:link, a.disabled:visited, a.disabled:active, a.disabled:hover { - color: #ffffff; - background: #999999; - border-color: #666666; -} - -a.icon, .linkOn.icon, .linkOff.icon, .selected.icon, .disabled.icon { - position: relative; - padding: 1px 4px 2px 20px; -} - -a.icon img, .linkOn.icon img, .linkOff.icon img, .selected.icon img, .disabled.icon img { - position: absolute; - top: 0; - left: 0; - width: 18px; - height: 18px; -} - -.linkDanger, a.linkDanger:link, a.linkDanger:visited, a.linkDanger:active { - color: #ffffff; - background-color: #ff0000; - border-color: #aa0000; -} - -.linkDanger:hover { - background-color: #ff6666; -} - -ul { - padding: 4px 0 0 10px; - margin: 0; - list-style-type: none; -} - -li { - padding: 0 0 2px 0; -} - -img, a img { - border-style: none; -} - -h1, h2, h3, h4, h5, h6 { - margin: 0; - padding: 12px 0 6px 0; - color: #FFFFFF; - clear: both; -} - -h1 { - font-size: 18px; -} - -h2 { - font-size: 16px; -} - -h3 { - font-size: 14px; -} - -h4 { - font-size: 12px; -} - -.white { - color: white; - font-weight: bold; -} - -.good { - color: #4f7529; - font-weight: bold; -} - -.average { - color: #cd6500; - font-weight: bold; -} - -.bad { - color: #ee0000; - font-weight: bold; -} - -.idle { - color: #272727; - font-weight: bold; -} - -.redButton { - background: #ea0000; -} - -.greenButton { - background: #00aa00; -} - -.yellowButton { - background: #cacc00; -} - -.highlight { - color: #8BA5C4; -} - -.dark { - color: #272727; -} - -.caption { - font-size: 10px; - font-weight: bold; - padding: 5px; -} - -.footer { - font-size: 10px; -} - -.multiLine { - white-space: pre-wrap; -} - -.noticePlaceholder { - position: relative; - font-size: 12px; - font-style: italic; - font-weight: bold; - padding: 3px 4px 3px 4px; - margin: 4px 0 4px 0; -} - -.notice { - position: relative; - background: url(uiNoticeBackground.jpg) 50% 50%; - color: #000000; - font-size: 12px; - font-style: italic; - font-weight: bold; - padding: 3px 4px 3px 4px; - margin: 4px 0 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; -} - -.itemGroup { - border: 1px solid #e9c183; - background: #2c2c2c; - padding: 4px; - clear: both; -} - -.item { - width: 100%; - margin: 4px 0 0 0; - clear: both; - overflow: auto; -} - -.itemContentNarrow, .itemContent, .itemContentWide, .itemContentSmall, .itemContentMedium { - float: left; -} - -.itemContentNarrow { - width: 30%; -} - -.itemContent { - width: 69%; -} - -.itemLabelNarrow, .itemLabel, .itemLabelWide, .itemLabelWider, .itemLabelWidest { - float: left; - color: #e9c183; -} - -.itemLabelNarrow { - width: 20%; -} - -.itemLabel { - width: 30%; -} - -.itemLabelWide { - width: 45%; -} - -.itemLabelWider { - width: 69%; -} - -.itemLabelWidest { - width: 100%; -} - -.itemContentWide { - width: 79%; -} - -.itemContentSmall { - width: 33%; -} - -.itemContentMedium { - width: 55%; -} - -.statusDisplay { - background: #000000; - color: #ffffff; - border: 1px solid #40628a; - padding: 4px; - margin: 3px 0; - overflow: hidden; -} - -.statusDisplayRecords { - background: #000000; - color: #ffffff; - border: 1px solid #40628a; - padding: 4px; - margin: 3px 0; - overflow-x: hidden; - overflow-y: auto; -} - -.statusDisplayComm { - width: 100%; - background: rgba(0, 0, 0, 0.5); - color: #ffffff; - padding-bottom: 4px; - border-top: 0 none; - border-left: 0 none; - border-right: 0 none; - border-bottom: 2px inset #40628a; - margin: 3px 0; - overflow: hidden; -} - -.statusLabel { - width: 138px; - float: left; - overflow: hidden; - color: #98B0C3; -} - -.statusValue { - float: left; -} - -.block { - padding: 8px; - margin: 10px 4px 4px 4px; - border: 1px solid #40628a; - background-color: #202020; -} - -.block h3 { - padding: 0; -} - -.displayBar { - position: relative; - width: 236px; - height: 16px; - border: 1px solid #666666; - float: left; - margin: 0 5px 0 0; - overflow: hidden; - background: #000000; -} - -.displayBarText, .displayBarVerticalText, .displayBarBeakerText{ - position: absolute; - top: -2px; - left: 5px; - width: 100%; - height: 100%; - color: #ffffff; - font-weight: normal; -} - -.displayBarFill { - width: 0%; - height: 100%; - background: #40628a; - overflow: hidden; - float: left; -} - -.displayBarVertical { - position: relative; - width: 16px; - height: 200px; - border: 1px solid #666666; - float: left; - margin: 0 5px 0 0; - overflow: hidden; - background: #40628a; -} - -.displayBarVerticalFill { - width: 100%; - height: 0%; - overflow: hidden; - float: left; - background: #000000; -} - -/*used in xenobio2 computer*/ - -.displayBarBeaker { - position: relative; - width: 100px; - height: 110px; - border-right: 2px solid rgb(102, 179, 255); - border-left: 2px solid rgb(102, 179, 255); - border-bottom: 2px solid rgb(102, 179, 255); - float: left; - margin: 0 5px 0 0; - overflow: hidden; - background: #40628a; -} - -.displayBarBeakerFill { - width: 100%; - height: 0%; - overflow: hidden; - float: left; - background: rgba(153, 204, 255, 0.3); -} - -.displayBarFill.alignRight { - float: right; -} - -.displayBarFill.good { - color: #ffffff; - background: #4f7529; -} - -.displayBarFill.average { - color: #ffffff; - background: #cd6500; -} - -.displayBarFill.bad { - color: #ffffff; - background: #ee0000; -} - -.displayBarFill.highlight { - color: #ffffff; - background: #8BA5C4; -} - -.clearBoth { - clear: both; -} - -.clearLeft { - clear: left; -} - -.clearRight { - clear: right; -} - -.line { - width: 100%; - clear: both; -} - -.inactive, a.inactive:link, a.inactive:visited, a.inactive:active, a.inactive:hover { - color: #ffffff; - background: #999999; - border-color: #666666; -} - -.fixedLeft { - width: 110px; - float: left; -} - -.fixedLeftWide { - width: 165px; - float: left; -} - -.fixedLeftWider { - width: 220px; - float: left; -} - -.fixedLeftWidest { - width: 250px; - float: left; -} - -.fixedLeftWiderRed { - width: 220px; - float: left; - background: #ee0000; -} - -.floatRight { - float: right; -} - -.floatLeft { - float: left; -} - -/* Used in PDA */ - -.wholeScreen { - position: absolute; - color: #517087; - font-size: 16px; - font-weight: bold; - text-align: center; -} - -.pdalink { - float: left; - white-space: nowrap; -} - -/* DNA Modifier UI (dna_modifier.tmpl) */ - -.dnaBlock { - float: left; - width: 90px; - padding: 0 0 5px 0; -} - -.dnaBlockNumber { - font-family: Fixed, monospace; - float: left; - color: #ffffff; - background: #363636; - min-width: 20px; - height: 20px; - padding: 0; - text-align: center; -} - -.dnaSubBlock { - font-family: Fixed, monospace; - float: left; - padding: 0; - min-width: 16px; - height: 20px; - text-align: center; -} - -.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; -} - -table.fixed { - table-layout:fixed; -} - -table.fixed td { - overflow: hidden; -} - -/* Table stuffs for power monitor */ -table.pmon { - border: 2px solid RoyalBlue; -} - -table.pmon td, table.pmon th { - border-bottom: 1px dotted black; - padding: 0px 5px 0px 5px; -} - -/* Table Stuffs for manifest*/ - -th.Command { - background: #3333FF; - font-weight: bold; - color: #ffffff; -} - -th.Security { - background: #8e0000; - font-weight: bold; - color: #ffffff; -} - -th.Medical { - background: #006600; - font-weight: bold; - color: #ffffff; -} - -th.Engineering { - background: #b27300; - font-weight: bold; - color: #ffffff; -} - -th.Science { - background: #a65ba6; - font-weight: bold; - color: #ffffff; -} - -th.Cargo { - background: #bb9040; - font-weight: bold; - color: #ffffff; -} - -th.Planetside{ - background: #555555; - font-weight: bold; - color: #ffffff; -} - -th.Civilian { - background: #a32800; - font-weight: bold; - color: #ffffff; -} - -th.Miscellaneous { - background: #666666; - font-weight: bold; - color: #ffffff; -} - -th.Silicon { - background: #222222; - font-weight: bold; - color: #ffffff; -} -/* Damage/health colors for crew monitoring computer */ - -.dead { - color: red; -} - -.alive { - color: #7cfc00; -} - -.burn { - color: orange; -} - -.brute { - color: red; -} - -.toxin { - color: lime; -} - -.oxyloss { - color: cyan; -} - -/* 75px width used in power monitoring console buttons */ -.width75btn { - width: 75px; -} - -/*Communicator Homescreen*/ -div.homeContainer { - width: 100%; - text-align: center; - margin: auto; - padding-top: 5px; -} - -div.homeScreen { - padding: 0 20px 0 20px; -} - -.link64 { - float: left; - min-width: 15px; - max-width: 68px; - height: 64px; - text-align: center; - color: #ffffff; - text-decoration: none; - background: rgba(64, 98, 138, 0.6); - border: 1px solid #161616; - padding: 0 0 4px 0; - margin: 0 0 30px 5.5%; - cursor: default; - border-radius: 10px; -} - -.link64:hover { - font-size: 13px; -} - -/*Communicator Dialing*/ -.dialPad { - clear: both; - text-align: center; - margin: auto; -} - -.dialPadKeys { - float: left; - width: 47px; - height: 47px; - font-size: 32px; - text-align: center; - color: #ffffff; - text-decoration: none; - background: rgba(64, 98, 138, 0.15); - border: 1px inset rgba(100, 100, 100, 0.25); - cursor: default; - line-height: 47px; -} - -.dialPadKeys:hover { - background: rgba(80, 122, 172, 0.5); -} - -.dialPadButtons { - float: left; - width: 63.2px; - height: 63.2px; - text-align: center; - color: #ffffff; - text-decoration: none; - background: rgba(64, 98, 138, 0.15); - border: 1px inset rgba(100, 100, 100, 0.25); - padding: 0 0 4px 0; - cursor: default; - margin-bottom: 25px; -} - -.dialPadButtons:hover { - background: rgba(80, 122, 172, 0.5); - font-size: 13px; - -} - -.dialPadAddress { - float: left; - width: 192px; - height: 18px; - background: rgba(64, 98, 138, 0.15); - color: #ffffff; - border-left: 1px inset #40628a; - border-top: 1px inset #40628a; - border-bottom: 1px inset #40628a; - -} - -.dialPadAddress:hover{ - background: rgba(80, 122, 172, 0.5); -} - -.dialPadClear { - float: left; - width: 19%; - height: 18px; - background: rgba(64, 98, 138, 0.15); - color: #ffffff; - border-right: 1px inset #40628a; - border-top: 1px inset #40628a; - border-bottom: 1px inset #40628a; -} - -.dialPadClear:hover{ - background: rgba(80, 122, 172, 0.5); -} \ No newline at end of file diff --git a/nano/css/shared_vr.css b/nano/css/shared_vr.css deleted file mode 100644 index a368b1fac5..0000000000 --- a/nano/css/shared_vr.css +++ /dev/null @@ -1,5 +0,0 @@ -th.Exploration{ - background: #bab421; - font-weight: bold; - color: #ffffff; -} \ No newline at end of file diff --git a/nano/images/nanomap_z1.png b/nano/images/nanomap_z1.png deleted file mode 100644 index bd575097c3..0000000000 Binary files a/nano/images/nanomap_z1.png and /dev/null differ diff --git a/nano/images/nanomap_z10.png b/nano/images/nanomap_z10.png deleted file mode 100644 index c12164d92e..0000000000 Binary files a/nano/images/nanomap_z10.png and /dev/null differ diff --git a/nano/images/nanomap_z13.png b/nano/images/nanomap_z13.png deleted file mode 100644 index 6f87d9911f..0000000000 Binary files a/nano/images/nanomap_z13.png and /dev/null differ diff --git a/nano/images/nanomap_z14.png b/nano/images/nanomap_z14.png deleted file mode 100644 index 84d106a5ac..0000000000 Binary files a/nano/images/nanomap_z14.png and /dev/null differ diff --git a/nano/images/nanomap_z2.png b/nano/images/nanomap_z2.png deleted file mode 100644 index 5ccd461808..0000000000 Binary files a/nano/images/nanomap_z2.png and /dev/null differ diff --git a/nano/images/nanomap_z3.png b/nano/images/nanomap_z3.png deleted file mode 100644 index 0761eed916..0000000000 Binary files a/nano/images/nanomap_z3.png and /dev/null differ diff --git a/nano/images/nanomap_z5.png b/nano/images/nanomap_z5.png deleted file mode 100644 index d8aece303d..0000000000 Binary files a/nano/images/nanomap_z5.png and /dev/null differ diff --git a/nano/images/nanomap_z6.png b/nano/images/nanomap_z6.png deleted file mode 100644 index 7fb5111527..0000000000 Binary files a/nano/images/nanomap_z6.png and /dev/null differ diff --git a/nano/images/nanomap_z7.png b/nano/images/nanomap_z7.png deleted file mode 100644 index 7645d78d09..0000000000 Binary files a/nano/images/nanomap_z7.png and /dev/null differ diff --git a/nano/images/nanomap_z8.png b/nano/images/nanomap_z8.png deleted file mode 100644 index c973b2b784..0000000000 Binary files a/nano/images/nanomap_z8.png and /dev/null differ diff --git a/nano/images/nanomap_z9.png b/nano/images/nanomap_z9.png deleted file mode 100644 index bff91820dd..0000000000 Binary files a/nano/images/nanomap_z9.png and /dev/null differ diff --git a/nano/images/pills32.png b/nano/images/pills32.png deleted file mode 100644 index 61459093c1..0000000000 Binary files a/nano/images/pills32.png and /dev/null differ diff --git a/nano/images/source/NTLogoRevised.fla b/nano/images/source/NTLogoRevised.fla deleted file mode 100644 index 47ea814344..0000000000 Binary files a/nano/images/source/NTLogoRevised.fla and /dev/null differ diff --git a/nano/images/source/icon-eye.xcf b/nano/images/source/icon-eye.xcf deleted file mode 100644 index 53ba738372..0000000000 Binary files a/nano/images/source/icon-eye.xcf and /dev/null differ diff --git a/nano/images/source/uiBackground-Syndicate.xcf b/nano/images/source/uiBackground-Syndicate.xcf deleted file mode 100644 index c86cea69d1..0000000000 Binary files a/nano/images/source/uiBackground-Syndicate.xcf and /dev/null differ diff --git a/nano/images/source/uiBackground.fla b/nano/images/source/uiBackground.fla deleted file mode 100644 index 60f9f1ee94..0000000000 Binary files a/nano/images/source/uiBackground.fla and /dev/null differ diff --git a/nano/images/source/uiBackground.xcf b/nano/images/source/uiBackground.xcf deleted file mode 100644 index d20db24ff8..0000000000 Binary files a/nano/images/source/uiBackground.xcf and /dev/null differ diff --git a/nano/images/source/uiBasicBackground.xcf b/nano/images/source/uiBasicBackground.xcf deleted file mode 100644 index 56a31d7b2f..0000000000 Binary files a/nano/images/source/uiBasicBackground.xcf and /dev/null differ diff --git a/nano/images/source/uiIcons16Green.xcf b/nano/images/source/uiIcons16Green.xcf deleted file mode 100644 index a7027a2873..0000000000 Binary files a/nano/images/source/uiIcons16Green.xcf and /dev/null differ diff --git a/nano/images/source/uiIcons16Red.xcf b/nano/images/source/uiIcons16Red.xcf deleted file mode 100644 index c07e4f64c7..0000000000 Binary files a/nano/images/source/uiIcons16Red.xcf and /dev/null differ diff --git a/nano/images/source/uiIcons24.xcf b/nano/images/source/uiIcons24.xcf deleted file mode 100644 index 5dcd8fd216..0000000000 Binary files a/nano/images/source/uiIcons24.xcf and /dev/null differ diff --git a/nano/images/source/uiIcons64.xcf b/nano/images/source/uiIcons64.xcf deleted file mode 100644 index 76c06ea1b6..0000000000 Binary files a/nano/images/source/uiIcons64.xcf and /dev/null differ diff --git a/nano/images/source/uiNoticeBackground.xcf b/nano/images/source/uiNoticeBackground.xcf deleted file mode 100644 index d1f074f102..0000000000 Binary files a/nano/images/source/uiNoticeBackground.xcf and /dev/null differ diff --git a/nano/images/source/uiTitleBackground.xcf b/nano/images/source/uiTitleBackground.xcf deleted file mode 100644 index 7de149075f..0000000000 Binary files a/nano/images/source/uiTitleBackground.xcf and /dev/null differ diff --git a/nano/images/status_icons/c_charging.gif b/nano/images/status_icons/c_charging.gif deleted file mode 100644 index e080e27cfc..0000000000 Binary files a/nano/images/status_icons/c_charging.gif and /dev/null differ diff --git a/nano/images/status_icons/c_discharging.gif b/nano/images/status_icons/c_discharging.gif deleted file mode 100644 index 793fa589c2..0000000000 Binary files a/nano/images/status_icons/c_discharging.gif and /dev/null differ diff --git a/nano/images/status_icons/c_max.gif b/nano/images/status_icons/c_max.gif deleted file mode 100644 index 7f26e51d20..0000000000 Binary files a/nano/images/status_icons/c_max.gif and /dev/null differ diff --git a/nano/images/uiBackground-Syndicate.png b/nano/images/uiBackground-Syndicate.png deleted file mode 100644 index 3ca932cb83..0000000000 Binary files a/nano/images/uiBackground-Syndicate.png and /dev/null differ diff --git a/nano/images/uiBackground.png b/nano/images/uiBackground.png deleted file mode 100644 index 32aa9dd7f6..0000000000 Binary files a/nano/images/uiBackground.png and /dev/null differ diff --git a/nano/images/uiBasicBackground.png b/nano/images/uiBasicBackground.png deleted file mode 100644 index 03131d1e94..0000000000 Binary files a/nano/images/uiBasicBackground.png and /dev/null differ diff --git a/nano/images/uiIcons16.png b/nano/images/uiIcons16.png deleted file mode 100644 index 2017c88d6c..0000000000 Binary files a/nano/images/uiIcons16.png and /dev/null differ diff --git a/nano/images/uiIcons16Green.png b/nano/images/uiIcons16Green.png deleted file mode 100644 index de0e33db1c..0000000000 Binary files a/nano/images/uiIcons16Green.png and /dev/null differ diff --git a/nano/images/uiIcons16Red.png b/nano/images/uiIcons16Red.png deleted file mode 100644 index 1c72dfe143..0000000000 Binary files a/nano/images/uiIcons16Red.png and /dev/null differ diff --git a/nano/images/uiIcons24.png b/nano/images/uiIcons24.png deleted file mode 100644 index ddf88b0dcd..0000000000 Binary files a/nano/images/uiIcons24.png and /dev/null differ diff --git a/nano/images/uiIcons64.png b/nano/images/uiIcons64.png deleted file mode 100644 index d849b3e869..0000000000 Binary files a/nano/images/uiIcons64.png and /dev/null differ diff --git a/nano/images/uiLinkPendingIcon.gif b/nano/images/uiLinkPendingIcon.gif deleted file mode 100644 index c3070fd157..0000000000 Binary files a/nano/images/uiLinkPendingIcon.gif and /dev/null differ diff --git a/nano/images/uiMaskBackground.png b/nano/images/uiMaskBackground.png deleted file mode 100644 index 6494f78a61..0000000000 Binary files a/nano/images/uiMaskBackground.png and /dev/null differ diff --git a/nano/images/uiNoticeBackground.jpg b/nano/images/uiNoticeBackground.jpg deleted file mode 100644 index dffe2f296b..0000000000 Binary files a/nano/images/uiNoticeBackground.jpg and /dev/null differ diff --git a/nano/images/uiTitleFluff-Syndicate.png b/nano/images/uiTitleFluff-Syndicate.png deleted file mode 100644 index b09f5ba6b2..0000000000 Binary files a/nano/images/uiTitleFluff-Syndicate.png and /dev/null differ diff --git a/nano/images/uiTitleFluff.png b/nano/images/uiTitleFluff.png deleted file mode 100644 index 513ba0c496..0000000000 Binary files a/nano/images/uiTitleFluff.png and /dev/null differ diff --git a/nano/js/libraries-old.min.js b/nano/js/libraries-old.min.js deleted file mode 100644 index fabe4e7dc5..0000000000 --- a/nano/js/libraries-old.min.js +++ /dev/null @@ -1 +0,0 @@ -(function(e,t){function H(e){var t=e.length,n=w.type(e);if(w.isWindow(e)){return false}if(e.nodeType===1&&t){return true}return n==="array"||n!=="function"&&(t===0||typeof t==="number"&&t>0&&t-1 in e)}function j(e){var t=B[e]={};w.each(e.match(S)||[],function(e,n){t[n]=true});return t}function q(e,n,r,i){if(!w.acceptData(e)){return}var s,o,u=w.expando,a=e.nodeType,f=a?w.cache:e,l=a?e[u]:e[u]&&u;if((!l||!f[l]||!i&&!f[l].data)&&r===t&&typeof n==="string"){return}if(!l){if(a){l=e[u]=c.pop()||w.guid++}else{l=u}}if(!f[l]){f[l]=a?{}:{toJSON:w.noop}}if(typeof n==="object"||typeof n==="function"){if(i){f[l]=w.extend(f[l],n)}else{f[l].data=w.extend(f[l].data,n)}}o=f[l];if(!i){if(!o.data){o.data={}}o=o.data}if(r!==t){o[w.camelCase(n)]=r}if(typeof n==="string"){s=o[n];if(s==null){s=o[w.camelCase(n)]}}else{s=o}return s}function R(e,t,n){if(!w.acceptData(e)){return}var r,i,s=e.nodeType,o=s?w.cache:e,u=s?e[w.expando]:w.expando;if(!o[u]){return}if(t){r=n?o[u]:o[u].data;if(r){if(!w.isArray(t)){if(t in r){t=[t]}else{t=w.camelCase(t);if(t in r){t=[t]}else{t=t.split(" ")}}}else{t=t.concat(w.map(t,w.camelCase))}i=t.length;while(i--){delete r[t[i]]}if(n?!z(r):!w.isEmptyObject(r)){return}}}if(!n){delete o[u].data;if(!z(o[u])){return}}if(s){w.cleanData([e],true)}else if(w.support.deleteExpando||o!=o.window){delete o[u]}else{o[u]=null}}function U(e,n,r){if(r===t&&e.nodeType===1){var i="data-"+n.replace(I,"-$1").toLowerCase();r=e.getAttribute(i);if(typeof r==="string"){try{r=r==="true"?true:r==="false"?false:r==="null"?null:+r+""===r?+r:F.test(r)?w.parseJSON(r):r}catch(s){}w.data(e,n,r)}else{r=t}}return r}function z(e){var t;for(t in e){if(t==="data"&&w.isEmptyObject(e[t])){continue}if(t!=="toJSON"){return false}}return true}function it(){return true}function st(){return false}function ot(){try{return o.activeElement}catch(e){}}function ct(e,t){do{e=e[t]}while(e&&e.nodeType!==1);return e}function ht(e,t,n){if(w.isFunction(t)){return w.grep(e,function(e,r){return!!t.call(e,r,e)!==n})}if(t.nodeType){return w.grep(e,function(e){return e===t!==n})}if(typeof t==="string"){if(ut.test(t)){return w.filter(t,e,n)}t=w.filter(t,e)}return w.grep(e,function(e){return w.inArray(e,t)>=0!==n})}function pt(e){var t=dt.split("|"),n=e.createDocumentFragment();if(n.createElement){while(t.length){n.createElement(t.pop())}}return n}function Mt(e,t){return w.nodeName(e,"table")&&w.nodeName(t.nodeType===1?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function _t(e){e.type=(w.find.attr(e,"type")!==null)+"/"+e.type;return e}function Dt(e){var t=Ct.exec(e.type);if(t){e.type=t[1]}else{e.removeAttribute("type")}return e}function Pt(e,t){var n,r=0;for(;(n=e[r])!=null;r++){w._data(n,"globalEval",!t||w._data(t[r],"globalEval"))}}function Ht(e,t){if(t.nodeType!==1||!w.hasData(e)){return}var n,r,i,s=w._data(e),o=w._data(t,s),u=s.events;if(u){delete o.handle;o.events={};for(n in u){for(r=0,i=u[n].length;r").css("cssText","display:block !important")).appendTo(t.documentElement);t=(It[0].contentWindow||It[0].contentDocument).document;t.write("");t.close();n=fn(e,t);It.detach()}Qt[e]=n}return n}function fn(e,t){var n=w(t.createElement(e)).appendTo(t.body),r=w.css(n[0],"display");n.remove();return r}function vn(e,t,n,r){var i;if(w.isArray(t)){w.each(t,function(t,i){if(n||cn.test(e)){r(e,i)}else{vn(e+"["+(typeof i==="object"?t:"")+"]",i,n,r)}})}else if(!n&&w.type(t)==="object"){for(i in t){vn(e+"["+i+"]",t[i],n,r)}}else{r(e,t)}}function _n(e){return function(t,n){if(typeof t!=="string"){n=t;t="*"}var r,i=0,s=t.toLowerCase().match(S)||[];if(w.isFunction(n)){while(r=s[i++]){if(r[0]==="+"){r=r.slice(1)||"*";(e[r]=e[r]||[]).unshift(n)}else{(e[r]=e[r]||[]).push(n)}}}}}function Dn(e,t,n,r){function o(u){var a;i[u]=true;w.each(e[u]||[],function(e,u){var f=u(t,n,r);if(typeof f==="string"&&!s&&!i[f]){t.dataTypes.unshift(f);o(f);return false}else if(s){return!(a=f)}});return a}var i={},s=e===An;return o(t.dataTypes[0])||!i["*"]&&o("*")}function Pn(e,n){var r,i,s=w.ajaxSettings.flatOptions||{};for(i in n){if(n[i]!==t){(s[i]?e:r||(r={}))[i]=n[i]}}if(r){w.extend(true,e,r)}return e}function Hn(e,n,r){var i,s,o,u,a=e.contents,f=e.dataTypes;while(f[0]==="*"){f.shift();if(s===t){s=e.mimeType||n.getResponseHeader("Content-Type")}}if(s){for(u in a){if(a[u]&&a[u].test(s)){f.unshift(u);break}}}if(f[0]in r){o=f[0]}else{for(u in r){if(!f[0]||e.converters[u+" "+f[0]]){o=u;break}if(!i){i=u}}o=o||i}if(o){if(o!==f[0]){f.unshift(o)}return r[o]}}function Bn(e,t,n,r){var i,s,o,u,a,f={},l=e.dataTypes.slice();if(l[1]){for(o in e.converters){f[o.toLowerCase()]=e.converters[o]}}s=l.shift();while(s){if(e.responseFields[s]){n[e.responseFields[s]]=t}if(!a&&r&&e.dataFilter){t=e.dataFilter(t,e.dataType)}a=s;s=l.shift();if(s){if(s==="*"){s=a}else if(a!=="*"&&a!==s){o=f[a+" "+s]||f["* "+s];if(!o){for(i in f){u=i.split(" ");if(u[1]===s){o=f[a+" "+u[0]]||f["* "+u[0]];if(o){if(o===true){o=f[i]}else if(f[i]!==true){s=u[0];l.unshift(u[1])}break}}}}if(o!==true){if(o&&e["throws"]){t=o(t)}else{try{t=o(t)}catch(c){return{state:"parsererror",error:o?c:"No conversion from "+a+" to "+s}}}}}}}return{state:"success",data:t}}function zn(){try{return new e.XMLHttpRequest}catch(t){}}function Wn(){try{return new e.ActiveXObject("Microsoft.XMLHTTP")}catch(t){}}function Yn(){setTimeout(function(){Xn=t});return Xn=w.now()}function Zn(e,t,n){var r,i=(Gn[t]||[]).concat(Gn["*"]),s=0,o=i.length;for(;s)[^>]*|#([\w-]*))$/,N=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,C=/^[\],:{}\s]*$/,k=/(?:^|:|,)(?:\s*\[)+/g,L=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,A=/"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,O=/^-ms-/,M=/-([\da-z])/gi,_=function(e,t){return t.toUpperCase()},D=function(e){if(o.addEventListener||e.type==="load"||o.readyState==="complete"){P();w.ready()}},P=function(){if(o.addEventListener){o.removeEventListener("DOMContentLoaded",D,false);e.removeEventListener("load",D,false)}else{o.detachEvent("onreadystatechange",D);e.detachEvent("onload",D)}};w.fn=w.prototype={jquery:h,constructor:w,init:function(e,n,r){var i,s;if(!e){return this}if(typeof e==="string"){if(e.charAt(0)==="<"&&e.charAt(e.length-1)===">"&&e.length>=3){i=[null,e,null]}else{i=T.exec(e)}if(i&&(i[1]||!n)){if(i[1]){n=n instanceof w?n[0]:n;w.merge(this,w.parseHTML(i[1],n&&n.nodeType?n.ownerDocument||n:o,true));if(N.test(i[1])&&w.isPlainObject(n)){for(i in n){if(w.isFunction(this[i])){this[i](n[i])}else{this.attr(i,n[i])}}}return this}else{s=o.getElementById(i[2]);if(s&&s.parentNode){if(s.id!==i[2]){return r.find(e)}this.length=1;this[0]=s}this.context=o;this.selector=e;return this}}else if(!n||n.jquery){return(n||r).find(e)}else{return this.constructor(n).find(e)}}else if(e.nodeType){this.context=this[0]=e;this.length=1;return this}else if(w.isFunction(e)){return r.ready(e)}if(e.selector!==t){this.selector=e.selector;this.context=e.context}return w.makeArray(e,this)},selector:"",length:0,toArray:function(){return v.call(this)},get:function(e){return e==null?this.toArray():e<0?this[this.length+e]:this[e]},pushStack:function(e){var t=w.merge(this.constructor(),e);t.prevObject=this;t.context=this.context;return t},each:function(e,t){return w.each(this,e,t)},ready:function(e){w.ready.promise().done(e);return this},slice:function(){return this.pushStack(v.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(n>=0&&n0){return}n.resolveWith(o,[w]);if(w.fn.trigger){w(o).trigger("ready").off("ready")}},isFunction:function(e){return w.type(e)==="function"},isArray:Array.isArray||function(e){return w.type(e)==="array"},isWindow:function(e){return e!=null&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){if(e==null){return String(e)}return typeof e==="object"||typeof e==="function"?l[g.call(e)]||"object":typeof e},isPlainObject:function(e){var n;if(!e||w.type(e)!=="object"||e.nodeType||w.isWindow(e)){return false}try{if(e.constructor&&!y.call(e,"constructor")&&!y.call(e.constructor.prototype,"isPrototypeOf")){return false}}catch(r){return false}if(w.support.ownLast){for(n in e){return y.call(e,n)}}for(n in e){}return n===t||y.call(e,n)},isEmptyObject:function(e){var t;for(t in e){return false}return true},error:function(e){throw new Error(e)},parseHTML:function(e,t,n){if(!e||typeof e!=="string"){return null}if(typeof t==="boolean"){n=t;t=false}t=t||o;var r=N.exec(e),i=!n&&[];if(r){return[t.createElement(r[1])]}r=w.buildFragment([e],t,i);if(i){w(i).remove()}return w.merge([],r.childNodes)},parseJSON:function(t){if(e.JSON&&e.JSON.parse){return e.JSON.parse(t)}if(t===null){return t}if(typeof t==="string"){t=w.trim(t);if(t){if(C.test(t.replace(L,"@").replace(A,"]").replace(k,""))){return(new Function("return "+t))()}}}w.error("Invalid JSON: "+t)},parseXML:function(n){var r,i;if(!n||typeof n!=="string"){return null}try{if(e.DOMParser){i=new DOMParser;r=i.parseFromString(n,"text/xml")}else{r=new ActiveXObject("Microsoft.XMLDOM");r.async="false";r.loadXML(n)}}catch(s){r=t}if(!r||!r.documentElement||r.getElementsByTagName("parsererror").length){w.error("Invalid XML: "+n)}return r},noop:function(){},globalEval:function(t){if(t&&w.trim(t)){(e.execScript||function(t){e["eval"].call(e,t)})(t)}},camelCase:function(e){return e.replace(O,"ms-").replace(M,_)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,s=e.length,o=H(e);if(n){if(o){for(;is.cacheLength){delete t[e.shift()]}return t[n]=r}var e=[];return t}function at(e){e[b]=true;return e}function ft(e){var t=h.createElement("div");try{return!!e(t)}catch(n){return false}finally{if(t.parentNode){t.parentNode.removeChild(t)}t=null}}function lt(e,t){var n=e.split("|"),r=e.length;while(r--){s.attrHandle[n[r]]=t}}function ct(e,t){var n=t&&e,r=n&&e.nodeType===1&&t.nodeType===1&&(~t.sourceIndex||O)-(~e.sourceIndex||O);if(r){return r}if(n){while(n=n.nextSibling){if(n===t){return-1}}}return e?1:-1}function ht(e){return function(t){var n=t.nodeName.toLowerCase();return n==="input"&&t.type===e}}function pt(e){return function(t){var n=t.nodeName.toLowerCase();return(n==="input"||n==="button")&&t.type===e}}function dt(e){return at(function(t){t=+t;return at(function(n,r){var i,s=e([],n.length,t),o=s.length;while(o--){if(n[i=s[o]]){n[i]=!(r[i]=n[i])}}})})}function vt(){}function mt(e,t){var n,r,i,o,u,a,f,l=N[e+" "];if(l){return t?0:l.slice(0)}u=e;a=[];f=s.preFilter;while(u){if(!n||(r=X.exec(u))){if(r){u=u.slice(r[0].length)||u}a.push(i=[])}n=false;if(r=V.exec(u)){n=r.shift();i.push({value:n,type:r[0].replace(W," ")});u=u.slice(n.length)}for(o in s.filter){if((r=G[o].exec(u))&&(!f[o]||(r=f[o](r)))){n=r.shift();i.push({value:n,type:o,matches:r});u=u.slice(n.length)}}if(!n){break}}return t?u.length:u?ot.error(e):N(e,a).slice(0)}function gt(e){var t=0,n=e.length,r="";for(;t1?function(t,n,r){var i=e.length;while(i--){if(!e[i](t,n,r)){return false}}return true}:e[0]}function wt(e,t,n,r,i){var s,o=[],u=0,a=e.length,f=t!=null;for(;u-1){s[f]=!(o[f]=c)}}}}else{g=wt(g===o?g.splice(d,g.length):g);if(i){i(null,o,g,a)}else{H.apply(o,g)}}})}function St(e){var t,n,r,i=e.length,o=s.relative[e[0].type],u=o||s.relative[" "],a=o?1:0,l=yt(function(e){return e===t},u,true),c=yt(function(e){return j.call(t,e)>-1},u,true),h=[function(e,n,r){return!o&&(r||n!==f)||((t=n).nodeType?l(e,n,r):c(e,n,r))}];for(;a1&&bt(h),a>1&>(e.slice(0,a-1).concat({value:e[a-2].type===" "?"*":""})).replace(W,"$1"),n,a0,o=e.length>0,u=function(u,a,l,c,p){var d,v,m,g=[],y=0,b="0",w=u&&[],E=p!=null,x=f,T=u||o&&s.find["TAG"]("*",p&&a.parentNode||a),N=S+=x==null?1:Math.random()||.1;if(E){f=a!==h&&a;i=n}for(;(d=T[b])!=null;b++){if(o&&d){v=0;while(m=e[v++]){if(m(d,a,l)){c.push(d);break}}if(E){S=N;i=++n}}if(r){if(d=!m&&d){y--}if(u){w.push(d)}}}y+=b;if(r&&b!==y){v=0;while(m=t[v++]){m(w,g,a,l)}if(u){if(y>0){while(b--){if(!(w[b]||g[b])){g[b]=D.call(c)}}}g=wt(g)}H.apply(c,g);if(E&&!u&&g.length>0&&y+t.length>1){ot.uniqueSort(c)}}if(E){S=N;f=x}return w};return r?at(u):u}function Tt(e,t,n){var r=0,i=t.length;for(;r2&&(f=u[0]).type==="ID"&&r.getById&&t.nodeType===9&&d&&s.relative[u[1].type]){t=(s.find["ID"](f.matches[0].replace(rt,it),t)||[])[0];if(!t){return n}e=e.slice(u.shift().value.length)}o=G["needsContext"].test(e)?0:u.length;while(o--){f=u[o];if(s.relative[l=f.type]){break}if(c=s.find[l]){if(i=c(f.matches[0].replace(rt,it),$.test(u[0].type)&&t.parentNode||t)){u.splice(o,1);e=i.length&>(u);if(!e){H.apply(n,i);return n}break}}}}}a(e,h)(i,t,!d,n,$.test(e));return n}var n,r,i,s,o,u,a,f,l,c,h,p,d,v,m,g,y,b="sizzle"+ -(new Date),E=e.document,S=0,x=0,T=ut(),N=ut(),C=ut(),k=false,L=function(e,t){if(e===t){k=true;return 0}return 0},A=typeof t,O=1<<31,M={}.hasOwnProperty,_=[],D=_.pop,P=_.push,H=_.push,B=_.slice,j=_.indexOf||function(e){var t=0,n=this.length;for(;t+~]|"+I+")"+I+"*"),$=new RegExp(I+"*[+~]"),J=new RegExp("="+I+"*([^\\]'\"]*)"+I+"*\\]","g"),K=new RegExp(z),Q=new RegExp("^"+R+"$"),G={ID:new RegExp("^#("+q+")"),CLASS:new RegExp("^\\.("+q+")"),TAG:new RegExp("^("+q.replace("w","w*")+")"),ATTR:new RegExp("^"+U),PSEUDO:new RegExp("^"+z),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+I+"*(even|odd|(([+-]|)(\\d*)n|)"+I+"*(?:([+-]|)"+I+"*(\\d+)|))"+I+"*\\)|)","i"),bool:new RegExp("^(?:"+F+")$","i"),needsContext:new RegExp("^"+I+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+I+"*((?:-\\d)?\\d*)"+I+"*\\)|)(?=[^-]|$)","i")},Y=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,et=/^(?:input|select|textarea|button)$/i,tt=/^h\d$/i,nt=/'|\\/g,rt=new RegExp("\\\\([\\da-f]{1,6}"+I+"?|("+I+")|.)","ig"),it=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,r&1023|56320)};try{H.apply(_=B.call(E.childNodes),E.childNodes);_[E.childNodes.length].nodeType}catch(st){H={apply:_.length?function(e,t){P.apply(e,B.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]){}e.length=n-1}}}u=ot.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?t.nodeName!=="HTML":false};r=ot.support={};c=ot.setDocument=function(e){var t=e?e.ownerDocument||e:E,n=t.defaultView;if(t===h||t.nodeType!==9||!t.documentElement){return h}h=t;p=t.documentElement;d=!u(t);if(n&&n.attachEvent&&n!==n.top){n.attachEvent("onbeforeunload",function(){c()})}r.attributes=ft(function(e){e.className="i";return!e.getAttribute("className")});r.getElementsByTagName=ft(function(e){e.appendChild(t.createComment(""));return!e.getElementsByTagName("*").length});r.getElementsByClassName=ft(function(e){e.innerHTML="
";e.firstChild.className="i";return e.getElementsByClassName("i").length===2});r.getById=ft(function(e){p.appendChild(e).id=b;return!t.getElementsByName||!t.getElementsByName(b).length});if(r.getById){s.find["ID"]=function(e,t){if(typeof t.getElementById!==A&&d){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}};s.filter["ID"]=function(e){var t=e.replace(rt,it);return function(e){return e.getAttribute("id")===t}}}else{delete s.find["ID"];s.filter["ID"]=function(e){var t=e.replace(rt,it);return function(e){var n=typeof e.getAttributeNode!==A&&e.getAttributeNode("id");return n&&n.value===t}}}s.find["TAG"]=r.getElementsByTagName?function(e,t){if(typeof t.getElementsByTagName!==A){return t.getElementsByTagName(e)}}:function(e,t){var n,r=[],i=0,s=t.getElementsByTagName(e);if(e==="*"){while(n=s[i++]){if(n.nodeType===1){r.push(n)}}return r}return s};s.find["CLASS"]=r.getElementsByClassName&&function(e,t){if(typeof t.getElementsByClassName!==A&&d){return t.getElementsByClassName(e)}};m=[];v=[];if(r.qsa=Y.test(t.querySelectorAll)){ft(function(e){e.innerHTML="";if(!e.querySelectorAll("[selected]").length){v.push("\\["+I+"*(?:value|"+F+")")}if(!e.querySelectorAll(":checked").length){v.push(":checked")}});ft(function(e){var n=t.createElement("input");n.setAttribute("type","hidden");e.appendChild(n).setAttribute("t","");if(e.querySelectorAll("[t^='']").length){v.push("[*^$]="+I+"*(?:''|\"\")")}if(!e.querySelectorAll(":enabled").length){v.push(":enabled",":disabled")}e.querySelectorAll("*,:x");v.push(",.*:")})}if(r.matchesSelector=Y.test(g=p.webkitMatchesSelector||p.mozMatchesSelector||p.oMatchesSelector||p.msMatchesSelector)){ft(function(e){r.disconnectedMatch=g.call(e,"div");g.call(e,"[s!='']:x");m.push("!=",z)})}v=v.length&&new RegExp(v.join("|"));m=m.length&&new RegExp(m.join("|"));y=Y.test(p.contains)||p.compareDocumentPosition?function(e,t){var n=e.nodeType===9?e.documentElement:e,r=t&&t.parentNode;return e===r||!!(r&&r.nodeType===1&&(n.contains?n.contains(r):e.compareDocumentPosition&&e.compareDocumentPosition(r)&16))}:function(e,t){if(t){while(t=t.parentNode){if(t===e){return true}}}return false};L=p.compareDocumentPosition?function(e,n){if(e===n){k=true;return 0}var i=n.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(n);if(i){if(i&1||!r.sortDetached&&n.compareDocumentPosition(e)===i){if(e===t||y(E,e)){return-1}if(n===t||y(E,n)){return 1}return l?j.call(l,e)-j.call(l,n):0}return i&4?-1:1}return e.compareDocumentPosition?-1:1}:function(e,n){var r,i=0,s=e.parentNode,o=n.parentNode,u=[e],a=[n];if(e===n){k=true;return 0}else if(!s||!o){return e===t?-1:n===t?1:s?-1:o?1:l?j.call(l,e)-j.call(l,n):0}else if(s===o){return ct(e,n)}r=e;while(r=r.parentNode){u.unshift(r)}r=n;while(r=r.parentNode){a.unshift(r)}while(u[i]===a[i]){i++}return i?ct(u[i],a[i]):u[i]===E?-1:a[i]===E?1:0};return t};ot.matches=function(e,t){return ot(e,null,null,t)};ot.matchesSelector=function(e,t){if((e.ownerDocument||e)!==h){c(e)}t=t.replace(J,"='$1']");if(r.matchesSelector&&d&&(!m||!m.test(t))&&(!v||!v.test(t))){try{var n=g.call(e,t);if(n||r.disconnectedMatch||e.document&&e.document.nodeType!==11){return n}}catch(i){}}return ot(t,h,null,[e]).length>0};ot.contains=function(e,t){if((e.ownerDocument||e)!==h){c(e)}return y(e,t)};ot.attr=function(e,n){if((e.ownerDocument||e)!==h){c(e)}var i=s.attrHandle[n.toLowerCase()],o=i&&M.call(s.attrHandle,n.toLowerCase())?i(e,n,!d):t;return o===t?r.attributes||!d?e.getAttribute(n):(o=e.getAttributeNode(n))&&o.specified?o.value:null:o};ot.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)};ot.uniqueSort=function(e){var t,n=[],i=0,s=0;k=!r.detectDuplicates;l=!r.sortStable&&e.slice(0);e.sort(L);if(k){while(t=e[s++]){if(t===e[s]){i=n.push(s)}}while(i--){e.splice(n[i],1)}}return e};o=ot.getText=function(e){var t,n="",r=0,i=e.nodeType;if(!i){for(;t=e[r];r++){n+=o(t)}}else if(i===1||i===9||i===11){if(typeof e.textContent==="string"){return e.textContent}else{for(e=e.firstChild;e;e=e.nextSibling){n+=o(e)}}}else if(i===3||i===4){return e.nodeValue}return n};s=ot.selectors={cacheLength:50,createPseudo:at,match:G,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:true}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:true},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){e[1]=e[1].replace(rt,it);e[3]=(e[4]||e[5]||"").replace(rt,it);if(e[2]==="~="){e[3]=" "+e[3]+" "}return e.slice(0,4)},CHILD:function(e){e[1]=e[1].toLowerCase();if(e[1].slice(0,3)==="nth"){if(!e[3]){ot.error(e[0])}e[4]=+(e[4]?e[5]+(e[6]||1):2*(e[3]==="even"||e[3]==="odd"));e[5]=+(e[7]+e[8]||e[3]==="odd")}else if(e[3]){ot.error(e[0])}return e},PSEUDO:function(e){var n,r=!e[5]&&e[2];if(G["CHILD"].test(e[0])){return null}if(e[3]&&e[4]!==t){e[2]=e[4]}else if(r&&K.test(r)&&(n=mt(r,true))&&(n=r.indexOf(")",r.length-n)-r.length)){e[0]=e[0].slice(0,n);e[2]=r.slice(0,n)}return e.slice(0,3)}},filter:{TAG:function(e){var t=e.replace(rt,it).toLowerCase();return e==="*"?function(){return true}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=T[e+" "];return t||(t=new RegExp("(^|"+I+")"+e+"("+I+"|$)"))&&T(e,function(e){return t.test(typeof e.className==="string"&&e.className||typeof e.getAttribute!==A&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=ot.attr(r,e);if(i==null){return t==="!="}if(!t){return true}i+="";return t==="="?i===n:t==="!="?i!==n:t==="^="?n&&i.indexOf(n)===0:t==="*="?n&&i.indexOf(n)>-1:t==="$="?n&&i.slice(-n.length)===n:t==="~="?(" "+i+" ").indexOf(n)>-1:t==="|="?i===n||i.slice(0,n.length+1)===n+"-":false}},CHILD:function(e,t,n,r,i){var s=e.slice(0,3)!=="nth",o=e.slice(-4)!=="last",u=t==="of-type";return r===1&&i===0?function(e){return!!e.parentNode}:function(t,n,a){var f,l,c,h,p,d,v=s!==o?"nextSibling":"previousSibling",m=t.parentNode,g=u&&t.nodeName.toLowerCase(),y=!a&&!u;if(m){if(s){while(v){c=t;while(c=c[v]){if(u?c.nodeName.toLowerCase()===g:c.nodeType===1){return false}}d=v=e==="only"&&!d&&"nextSibling"}return true}d=[o?m.firstChild:m.lastChild];if(o&&y){l=m[b]||(m[b]={});f=l[e]||[];p=f[0]===S&&f[1];h=f[0]===S&&f[2];c=p&&m.childNodes[p];while(c=++p&&c&&c[v]||(h=p=0)||d.pop()){if(c.nodeType===1&&++h&&c===t){l[e]=[S,p,h];break}}}else if(y&&(f=(t[b]||(t[b]={}))[e])&&f[0]===S){h=f[1]}else{while(c=++p&&c&&c[v]||(h=p=0)||d.pop()){if((u?c.nodeName.toLowerCase()===g:c.nodeType===1)&&++h){if(y){(c[b]||(c[b]={}))[e]=[S,h]}if(c===t){break}}}}h-=i;return h===r||h%r===0&&h/r>=0}}},PSEUDO:function(e,t){var n,r=s.pseudos[e]||s.setFilters[e.toLowerCase()]||ot.error("unsupported pseudo: "+e);if(r[b]){return r(t)}if(r.length>1){n=[e,e,"",t];return s.setFilters.hasOwnProperty(e.toLowerCase())?at(function(e,n){var i,s=r(e,t),o=s.length;while(o--){i=j.call(e,s[o]);e[i]=!(n[i]=s[o])}}):function(e){return r(e,0,n)}}return r}},pseudos:{not:at(function(e){var t=[],n=[],r=a(e.replace(W,"$1"));return r[b]?at(function(e,t,n,i){var s,o=r(e,null,i,[]),u=e.length;while(u--){if(s=o[u]){e[u]=!(t[u]=s)}}}):function(e,i,s){t[0]=e;r(t,null,s,n);return!n.pop()}}),has:at(function(e){return function(t){return ot(e,t).length>0}}),contains:at(function(e){return function(t){return(t.textContent||t.innerText||o(t)).indexOf(e)>-1}}),lang:at(function(e){if(!Q.test(e||"")){ot.error("unsupported lang: "+e)}e=e.replace(rt,it).toLowerCase();return function(t){var n;do{if(n=d?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang")){n=n.toLowerCase();return n===e||n.indexOf(e+"-")===0}}while((t=t.parentNode)&&t.nodeType===1);return false}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===p},focus:function(e){return e===h.activeElement&&(!h.hasFocus||h.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===false},disabled:function(e){return e.disabled===true},checked:function(e){var t=e.nodeName.toLowerCase();return t==="input"&&!!e.checked||t==="option"&&!!e.selected},selected:function(e){if(e.parentNode){e.parentNode.selectedIndex}return e.selected===true},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling){if(e.nodeName>"@"||e.nodeType===3||e.nodeType===4){return false}}return true},parent:function(e){return!s.pseudos["empty"](e)},header:function(e){return tt.test(e.nodeName)},input:function(e){return et.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return t==="input"&&e.type==="button"||t==="button"},text:function(e){var t;return e.nodeName.toLowerCase()==="input"&&e.type==="text"&&((t=e.getAttribute("type"))==null||t.toLowerCase()===e.type)},first:dt(function(){return[0]}),last:dt(function(e,t){return[t-1]}),eq:dt(function(e,t,n){return[n<0?n+t:n]}),even:dt(function(e,t){var n=0;for(;n=0;){e.push(r)}return e}),gt:dt(function(e,t,n){var r=n<0?n+t:n;for(;++r";e.firstChild.setAttribute("value","");return e.firstChild.getAttribute("value")===""})){lt("value",function(e,t,n){if(!n&&e.nodeName.toLowerCase()==="input"){return e.defaultValue}})}if(!ft(function(e){return e.getAttribute("disabled")==null})){lt(F,function(e,t,n){var r;if(!n){return(r=e.getAttributeNode(t))&&r.specified?r.value:e[t]===true?t.toLowerCase():null}})}w.find=ot;w.expr=ot.selectors;w.expr[":"]=w.expr.pseudos;w.unique=ot.uniqueSort;w.text=ot.getText;w.isXMLDoc=ot.isXML;w.contains=ot.contains})(e);var B={};w.Callbacks=function(e){e=typeof e==="string"?B[e]||j(e):w.extend({},e);var n,r,i,s,o,u,a=[],f=!e.once&&[],l=function(t){r=e.memory&&t;i=true;o=u||0;u=0;s=a.length;n=true;for(;a&&o-1){a.splice(r,1);if(n){if(r<=s){s--}if(r<=o){o--}}}})}return this},has:function(e){return e?w.inArray(e,a)>-1:!!(a&&a.length)},empty:function(){a=[];s=0;return this},disable:function(){a=f=r=t;return this},disabled:function(){return!a},lock:function(){f=t;if(!r){c.disable()}return this},locked:function(){return!f},fireWith:function(e,t){if(a&&(!i||f)){t=t||[];t=[e,t.slice?t.slice():t];if(n){f.push(t)}else{l(t)}}return this},fire:function(){c.fireWith(this,arguments);return this},fired:function(){return!!i}};return c};w.extend({Deferred:function(e){var t=[["resolve","done",w.Callbacks("once memory"),"resolved"],["reject","fail",w.Callbacks("once memory"),"rejected"],["notify","progress",w.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){i.done(arguments).fail(arguments);return this},then:function(){var e=arguments;return w.Deferred(function(n){w.each(t,function(t,s){var o=s[0],u=w.isFunction(e[t])&&e[t];i[s[1]](function(){var e=u&&u.apply(this,arguments);if(e&&w.isFunction(e.promise)){e.promise().done(n.resolve).fail(n.reject).progress(n.notify)}else{n[o+"With"](this===r?n.promise():this,u?[e]:arguments)}})});e=null}).promise()},promise:function(e){return e!=null?w.extend(e,r):r}},i={};r.pipe=r.then;w.each(t,function(e,s){var o=s[2],u=s[3];r[s[1]]=o.add;if(u){o.add(function(){n=u},t[e^1][2].disable,t[2][2].lock)}i[s[0]]=function(){i[s[0]+"With"](this===i?r:this,arguments);return this};i[s[0]+"With"]=o.fireWith});r.promise(i);if(e){e.call(i,i)}return i},when:function(e){var t=0,n=v.call(arguments),r=n.length,i=r!==1||e&&w.isFunction(e.promise)?r:0,s=i===1?e:w.Deferred(),o=function(e,t,n){return function(r){t[e]=this;n[e]=arguments.length>1?v.call(arguments):r;if(n===u){s.notifyWith(t,n)}else if(!--i){s.resolveWith(t,n)}}},u,a,f;if(r>1){u=new Array(r);a=new Array(r);f=new Array(r);for(;t
a";n=p.getElementsByTagName("*")||[];r=p.getElementsByTagName("a")[0];if(!r||!r.style||!n.length){return t}u=o.createElement("select");f=u.appendChild(o.createElement("option"));s=p.getElementsByTagName("input")[0];r.style.cssText="top:1px;float:left;opacity:.5";t.getSetAttribute=p.className!=="t";t.leadingWhitespace=p.firstChild.nodeType===3;t.tbody=!p.getElementsByTagName("tbody").length;t.htmlSerialize=!!p.getElementsByTagName("link").length;t.style=/top/.test(r.getAttribute("style"));t.hrefNormalized=r.getAttribute("href")==="/a";t.opacity=/^0.5/.test(r.style.opacity);t.cssFloat=!!r.style.cssFloat;t.checkOn=!!s.value;t.optSelected=f.selected;t.enctype=!!o.createElement("form").enctype;t.html5Clone=o.createElement("nav").cloneNode(true).outerHTML!=="<:nav>";t.inlineBlockNeedsLayout=false;t.shrinkWrapBlocks=false;t.pixelPosition=false;t.deleteExpando=true;t.noCloneEvent=true;t.reliableMarginRight=true;t.boxSizingReliable=true;s.checked=true;t.noCloneChecked=s.cloneNode(true).checked;u.disabled=true;t.optDisabled=!f.disabled;try{delete p.test}catch(d){t.deleteExpando=false}s=o.createElement("input");s.setAttribute("value","");t.input=s.getAttribute("value")==="";s.value="t";s.setAttribute("type","radio");t.radioValue=s.value==="t";s.setAttribute("checked","t");s.setAttribute("name","t");a=o.createDocumentFragment();a.appendChild(s);t.appendChecked=s.checked;t.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;if(p.attachEvent){p.attachEvent("onclick",function(){t.noCloneEvent=false});p.cloneNode(true).click()}for(h in{submit:true,change:true,focusin:true}){p.setAttribute(l="on"+h,"t");t[h+"Bubbles"]=l in e||p.attributes[l].expando===false}p.style.backgroundClip="content-box";p.cloneNode(true).style.backgroundClip="";t.clearCloneStyle=p.style.backgroundClip==="content-box";for(h in w(t)){break}t.ownLast=h!=="0";w(function(){var n,r,s,u="padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",a=o.getElementsByTagName("body")[0];if(!a){return}n=o.createElement("div");n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px";a.appendChild(n).appendChild(p);p.innerHTML="
t
";s=p.getElementsByTagName("td");s[0].style.cssText="padding:0;margin:0;border:0;display:none";c=s[0].offsetHeight===0;s[0].style.display="";s[1].style.display="none";t.reliableHiddenOffsets=c&&s[0].offsetHeight===0;p.innerHTML="";p.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;";w.swap(a,a.style.zoom!=null?{zoom:1}:{},function(){t.boxSizing=p.offsetWidth===4});if(e.getComputedStyle){t.pixelPosition=(e.getComputedStyle(p,null)||{}).top!=="1%";t.boxSizingReliable=(e.getComputedStyle(p,null)||{width:"4px"}).width==="4px";r=p.appendChild(o.createElement("div"));r.style.cssText=p.style.cssText=u;r.style.marginRight=r.style.width="0";p.style.width="1px";t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)}if(typeof p.style.zoom!==i){p.innerHTML="";p.style.cssText=u+"width:1px;padding:1px;display:inline;zoom:1";t.inlineBlockNeedsLayout=p.offsetWidth===3;p.style.display="block";p.innerHTML="
";p.firstChild.style.width="5px";t.shrinkWrapBlocks=p.offsetWidth!==3;if(t.inlineBlockNeedsLayout){a.style.zoom=1}}a.removeChild(n);n=p=s=r=null});n=u=a=f=r=s=null;return t}({});var F=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,I=/([A-Z])/g;w.extend({cache:{},noData:{applet:true,embed:true,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(e){e=e.nodeType?w.cache[e[w.expando]]:e[w.expando];return!!e&&!z(e)},data:function(e,t,n){return q(e,t,n)},removeData:function(e,t){return R(e,t)},_data:function(e,t,n){return q(e,t,n,true)},_removeData:function(e,t){return R(e,t,true)},acceptData:function(e){if(e.nodeType&&e.nodeType!==1&&e.nodeType!==9){return false}var t=e.nodeName&&w.noData[e.nodeName.toLowerCase()];return!t||t!==true&&e.getAttribute("classid")===t}});w.fn.extend({data:function(e,n){var r,i,s=null,o=0,u=this[0];if(e===t){if(this.length){s=w.data(u);if(u.nodeType===1&&!w._data(u,"parsedAttrs")){r=u.attributes;for(;o1?this.each(function(){w.data(this,e,n)}):u?U(u,e,w.data(u,e)):null},removeData:function(e){return this.each(function(){w.removeData(this,e)})}});w.extend({queue:function(e,t,n){var r;if(e){t=(t||"fx")+"queue";r=w._data(e,t);if(n){if(!r||w.isArray(n)){r=w._data(e,t,w.makeArray(n))}else{r.push(n)}}return r||[]}},dequeue:function(e,t){t=t||"fx";var n=w.queue(e,t),r=n.length,i=n.shift(),s=w._queueHooks(e,t),o=function(){w.dequeue(e,t)};if(i==="inprogress"){i=n.shift();r--}if(i){if(t==="fx"){n.unshift("inprogress")}delete s.stop;i.call(e,o,s)}if(!r&&s){s.empty.fire()}},_queueHooks:function(e,t){var n=t+"queueHooks";return w._data(e,n)||w._data(e,n,{empty:w.Callbacks("once memory").add(function(){w._removeData(e,t+"queue");w._removeData(e,n)})})}});w.fn.extend({queue:function(e,n){var r=2;if(typeof e!=="string"){n=e;e="fx";r--}if(arguments.length1)},removeAttr:function(e){return this.each(function(){w.removeAttr(this,e)})},prop:function(e,t){return w.access(this,w.prop,e,t,arguments.length>1)},removeProp:function(e){e=w.propFix[e]||e;return this.each(function(){try{this[e]=t;delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,s,o=0,u=this.length,a=typeof e==="string"&&e;if(w.isFunction(e)){return this.each(function(t){w(this).addClass(e.call(this,t,this.className))})}if(a){t=(e||"").match(S)||[];for(;o=0){r=r.replace(" "+i+" "," ")}}n.className=e?w.trim(r):""}}}return this},toggleClass:function(e,t){var n=typeof e;if(typeof t==="boolean"&&n==="string"){return t?this.addClass(e):this.removeClass(e)}if(w.isFunction(e)){return this.each(function(n){w(this).toggleClass(e.call(this,n,this.className,t),t)})}return this.each(function(){if(n==="string"){var t,r=0,s=w(this),o=e.match(S)||[];while(t=o[r++]){if(s.hasClass(t)){s.removeClass(t)}else{s.addClass(t)}}}else if(n===i||n==="boolean"){if(this.className){w._data(this,"__className__",this.className)}this.className=this.className||e===false?"":w._data(this,"__className__")||""}})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;n=0){return true}}return false},val:function(e){var n,r,i,s=this[0];if(!arguments.length){if(s){r=w.valHooks[s.type]||w.valHooks[s.nodeName.toLowerCase()];if(r&&"get"in r&&(n=r.get(s,"value"))!==t){return n}n=s.value;return typeof n==="string"?n.replace($,""):n==null?"":n}return}i=w.isFunction(e);return this.each(function(n){var s;if(this.nodeType!==1){return}if(i){s=e.call(this,n,w(this).val())}else{s=e}if(s==null){s=""}else if(typeof s==="number"){s+=""}else if(w.isArray(s)){s=w.map(s,function(e){return e==null?"":e+""})}r=w.valHooks[this.type]||w.valHooks[this.nodeName.toLowerCase()];if(!r||!("set"in r)||r.set(this,s,"value")===t){this.value=s}})}});w.extend({valHooks:{option:{get:function(e){var t=w.find.attr(e,"value");return t!=null?t:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,s=e.type==="select-one"||i<0,o=s?null:[],u=s?i+1:r.length,a=i<0?u:s?i:0;for(;a=0){n=true}}if(!n){e.selectedIndex=-1}return s}}},attr:function(e,n,r){var s,o,u=e.nodeType;if(!e||u===3||u===8||u===2){return}if(typeof e.getAttribute===i){return w.prop(e,n,r)}if(u!==1||!w.isXMLDoc(e)){n=n.toLowerCase();s=w.attrHooks[n]||(w.expr.match.bool.test(n)?X:W)}if(r!==t){if(r===null){w.removeAttr(e,n)}else if(s&&"set"in s&&(o=s.set(e,r,n))!==t){return o}else{e.setAttribute(n,r+"");return r}}else if(s&&"get"in s&&(o=s.get(e,n))!==null){return o}else{o=w.find.attr(e,n);return o==null?t:o}},removeAttr:function(e,t){var n,r,i=0,s=t&&t.match(S);if(s&&e.nodeType===1){while(n=s[i++]){r=w.propFix[n]||n;if(w.expr.match.bool.test(n)){if(Y&&G||!Q.test(n)){e[r]=false}else{e[w.camelCase("default-"+n)]=e[r]=false}}else{w.attr(e,n,"")}e.removeAttribute(G?n:r)}}},attrHooks:{type:{set:function(e,t){if(!w.support.radioValue&&t==="radio"&&w.nodeName(e,"input")){var n=e.value;e.setAttribute("type",t);if(n){e.value=n}return t}}}},propFix:{"for":"htmlFor","class":"className"},prop:function(e,n,r){var i,s,o,u=e.nodeType;if(!e||u===3||u===8||u===2){return}o=u!==1||!w.isXMLDoc(e);if(o){n=w.propFix[n]||n;s=w.propHooks[n]}if(r!==t){return s&&"set"in s&&(i=s.set(e,r,n))!==t?i:e[n]=r}else{return s&&"get"in s&&(i=s.get(e,n))!==null?i:e[n]}},propHooks:{tabIndex:{get:function(e){var t=w.find.attr(e,"tabindex");return t?parseInt(t,10):J.test(e.nodeName)||K.test(e.nodeName)&&e.href?0:-1}}}});X={set:function(e,t,n){if(t===false){w.removeAttr(e,n)}else if(Y&&G||!Q.test(n)){e.setAttribute(!G&&w.propFix[n]||n,n)}else{e[w.camelCase("default-"+n)]=e[n]=true}return n}};w.each(w.expr.match.bool.source.match(/\w+/g),function(e,n){var r=w.expr.attrHandle[n]||w.find.attr;w.expr.attrHandle[n]=Y&&G||!Q.test(n)?function(e,n,i){var s=w.expr.attrHandle[n],o=i?t:(w.expr.attrHandle[n]=t)!=r(e,n,i)?n.toLowerCase():null;w.expr.attrHandle[n]=s;return o}:function(e,n,r){return r?t:e[w.camelCase("default-"+n)]?n.toLowerCase():null}});if(!Y||!G){w.attrHooks.value={set:function(e,t,n){if(w.nodeName(e,"input")){e.defaultValue=t}else{return W&&W.set(e,t,n)}}}}if(!G){W={set:function(e,n,r){var i=e.getAttributeNode(r);if(!i){e.setAttributeNode(i=e.ownerDocument.createAttribute(r))}i.value=n+="";return r==="value"||n===e.getAttribute(r)?n:t}};w.expr.attrHandle.id=w.expr.attrHandle.name=w.expr.attrHandle.coords=function(e,n,r){var i;return r?t:(i=e.getAttributeNode(n))&&i.value!==""?i.value:null};w.valHooks.button={get:function(e,n){var r=e.getAttributeNode(n);return r&&r.specified?r.value:t},set:W.set};w.attrHooks.contenteditable={set:function(e,t,n){W.set(e,t===""?false:t,n)}};w.each(["width","height"],function(e,t){w.attrHooks[t]={set:function(e,n){if(n===""){e.setAttribute(t,"auto");return n}}}})}if(!w.support.hrefNormalized){w.each(["href","src"],function(e,t){w.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}})}if(!w.support.style){w.attrHooks.style={get:function(e){return e.style.cssText||t},set:function(e,t){return e.style.cssText=t+""}}}if(!w.support.optSelected){w.propHooks.selected={get:function(e){var t=e.parentNode;if(t){t.selectedIndex;if(t.parentNode){t.parentNode.selectedIndex}}return null}}}w.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){w.propFix[this.toLowerCase()]=this});if(!w.support.enctype){w.propFix.enctype="encoding"}w.each(["radio","checkbox"],function(){w.valHooks[this]={set:function(e,t){if(w.isArray(t)){return e.checked=w.inArray(w(e).val(),t)>=0}}};if(!w.support.checkOn){w.valHooks[this].get=function(e){return e.getAttribute("value")===null?"on":e.value}}});var Z=/^(?:input|select|textarea)$/i,et=/^key/,tt=/^(?:mouse|contextmenu)|click/,nt=/^(?:focusinfocus|focusoutblur)$/,rt=/^([^.]*)(?:\.(.+)|)$/;w.event={global:{},add:function(e,n,r,s,o){var u,a,f,l,c,h,p,d,v,m,g,y=w._data(e);if(!y){return}if(r.handler){l=r;r=l.handler;o=l.selector}if(!r.guid){r.guid=w.guid++}if(!(a=y.events)){a=y.events={}}if(!(h=y.handle)){h=y.handle=function(e){return typeof w!==i&&(!e||w.event.triggered!==e.type)?w.event.dispatch.apply(h.elem,arguments):t};h.elem=e}n=(n||"").match(S)||[""];f=n.length;while(f--){u=rt.exec(n[f])||[];v=g=u[1];m=(u[2]||"").split(".").sort();if(!v){continue}c=w.event.special[v]||{};v=(o?c.delegateType:c.bindType)||v;c=w.event.special[v]||{};p=w.extend({type:v,origType:g,data:s,handler:r,guid:r.guid,selector:o,needsContext:o&&w.expr.match.needsContext.test(o),namespace:m.join(".")},l);if(!(d=a[v])){d=a[v]=[];d.delegateCount=0;if(!c.setup||c.setup.call(e,s,m,h)===false){if(e.addEventListener){e.addEventListener(v,h,false)}else if(e.attachEvent){e.attachEvent("on"+v,h)}}}if(c.add){c.add.call(e,p);if(!p.handler.guid){p.handler.guid=r.guid}}if(o){d.splice(d.delegateCount++,0,p)}else{d.push(p)}w.event.global[v]=true}e=null},remove:function(e,t,n,r,i){var s,o,u,a,f,l,c,h,p,d,v,m=w.hasData(e)&&w._data(e);if(!m||!(l=m.events)){return}t=(t||"").match(S)||[""];f=t.length;while(f--){u=rt.exec(t[f])||[];p=v=u[1];d=(u[2]||"").split(".").sort();if(!p){for(p in l){w.event.remove(e,p+t[f],n,r,true)}continue}c=w.event.special[p]||{};p=(r?c.delegateType:c.bindType)||p;h=l[p]||[];u=u[2]&&new RegExp("(^|\\.)"+d.join("\\.(?:.*\\.|)")+"(\\.|$)");a=s=h.length;while(s--){o=h[s];if((i||v===o.origType)&&(!n||n.guid===o.guid)&&(!u||u.test(o.namespace))&&(!r||r===o.selector||r==="**"&&o.selector)){h.splice(s,1);if(o.selector){h.delegateCount--}if(c.remove){c.remove.call(e,o)}}}if(a&&!h.length){if(!c.teardown||c.teardown.call(e,d,m.handle)===false){w.removeEvent(e,p,m.handle)}delete l[p]}}if(w.isEmptyObject(l)){delete m.handle;w._removeData(e,"events")}},trigger:function(n,r,i,s){var u,a,f,l,c,h,p,d=[i||o],v=y.call(n,"type")?n.type:n,m=y.call(n,"namespace")?n.namespace.split("."):[];f=h=i=i||o;if(i.nodeType===3||i.nodeType===8){return}if(nt.test(v+w.event.triggered)){return}if(v.indexOf(".")>=0){m=v.split(".");v=m.shift();m.sort()}a=v.indexOf(":")<0&&"on"+v;n=n[w.expando]?n:new w.Event(v,typeof n==="object"&&n);n.isTrigger=s?2:3;n.namespace=m.join(".");n.namespace_re=n.namespace?new RegExp("(^|\\.)"+m.join("\\.(?:.*\\.|)")+"(\\.|$)"):null;n.result=t;if(!n.target){n.target=i}r=r==null?[n]:w.makeArray(r,[n]);c=w.event.special[v]||{};if(!s&&c.trigger&&c.trigger.apply(i,r)===false){return}if(!s&&!c.noBubble&&!w.isWindow(i)){l=c.delegateType||v;if(!nt.test(l+v)){f=f.parentNode}for(;f;f=f.parentNode){d.push(f);h=f}if(h===(i.ownerDocument||o)){d.push(h.defaultView||h.parentWindow||e)}}p=0;while((f=d[p++])&&!n.isPropagationStopped()){n.type=p>1?l:c.bindType||v;u=(w._data(f,"events")||{})[n.type]&&w._data(f,"handle");if(u){u.apply(f,r)}u=a&&f[a];if(u&&w.acceptData(f)&&u.apply&&u.apply(f,r)===false){n.preventDefault()}}n.type=v;if(!s&&!n.isDefaultPrevented()){if((!c._default||c._default.apply(d.pop(),r)===false)&&w.acceptData(i)){if(a&&i[v]&&!w.isWindow(i)){h=i[a];if(h){i[a]=null}w.event.triggered=v;try{i[v]()}catch(g){}w.event.triggered=t;if(h){i[a]=h}}}}return n.result},dispatch:function(e){e=w.event.fix(e);var n,r,i,s,o,u=[],a=v.call(arguments),f=(w._data(this,"events")||{})[e.type]||[],l=w.event.special[e.type]||{};a[0]=e;e.delegateTarget=this;if(l.preDispatch&&l.preDispatch.call(this,e)===false){return}u=w.event.handlers.call(this,e,f);n=0;while((s=u[n++])&&!e.isPropagationStopped()){e.currentTarget=s.elem;o=0;while((i=s.handlers[o++])&&!e.isImmediatePropagationStopped()){if(!e.namespace_re||e.namespace_re.test(i.namespace)){e.handleObj=i;e.data=i.data;r=((w.event.special[i.origType]||{}).handle||i.handler).apply(s.elem,a);if(r!==t){if((e.result=r)===false){e.preventDefault();e.stopPropagation()}}}}}if(l.postDispatch){l.postDispatch.call(this,e)}return e.result},handlers:function(e,n){var r,i,s,o,u=[],a=n.delegateCount,f=e.target;if(a&&f.nodeType&&(!e.button||e.type!=="click")){for(;f!=this;f=f.parentNode||this){if(f.nodeType===1&&(f.disabled!==true||e.type!=="click")){s=[];for(o=0;o=0:w.find(r,this,null,[f]).length}if(s[r]){s.push(i)}}if(s.length){u.push({elem:f,handlers:s})}}}}if(a1?w.unique(n):n);n.selector=this.selector?this.selector+" "+e:e;return n},has:function(e){var t,n=w(e,this),r=n.length;return this.filter(function(){for(t=0;t-1:n.nodeType===1&&w.find.matchesSelector(n,e))){n=s.push(n);break}}}return this.pushStack(s.length>1?w.unique(s):s)},index:function(e){if(!e){return this[0]&&this[0].parentNode?this.first().prevAll().length:-1}if(typeof e==="string"){return w.inArray(this[0],w(e))}return w.inArray(e.jquery?e[0]:e,this)},add:function(e,t){var n=typeof e==="string"?w(e,t):w.makeArray(e&&e.nodeType?[e]:e),r=w.merge(this.get(),n);return this.pushStack(w.unique(r))},addBack:function(e){return this.add(e==null?this.prevObject:this.prevObject.filter(e))}});w.each({parent:function(e){var t=e.parentNode;return t&&t.nodeType!==11?t:null},parents:function(e){return w.dir(e,"parentNode")},parentsUntil:function(e,t,n){return w.dir(e,"parentNode",n)},next:function(e){return ct(e,"nextSibling")},prev:function(e){return ct(e,"previousSibling")},nextAll:function(e){return w.dir(e,"nextSibling")},prevAll:function(e){return w.dir(e,"previousSibling")},nextUntil:function(e,t,n){return w.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return w.dir(e,"previousSibling",n)},siblings:function(e){return w.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return w.sibling(e.firstChild)},contents:function(e){return w.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:w.merge([],e.childNodes)}},function(e,t){w.fn[e]=function(n,r){var i=w.map(this,t,n);if(e.slice(-5)!=="Until"){r=n}if(r&&typeof r==="string"){i=w.filter(r,i)}if(this.length>1){if(!lt[e]){i=w.unique(i)}if(at.test(e)){i=i.reverse()}}return this.pushStack(i)}});w.extend({filter:function(e,t,n){var r=t[0];if(n){e=":not("+e+")"}return t.length===1&&r.nodeType===1?w.find.matchesSelector(r,e)?[r]:[]:w.find.matches(e,w.grep(t,function(e){return e.nodeType===1}))},dir:function(e,n,r){var i=[],s=e[n];while(s&&s.nodeType!==9&&(r===t||s.nodeType!==1||!w(s).is(r))){if(s.nodeType===1){i.push(s)}s=s[n]}return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling){if(e.nodeType===1&&e!==t){n.push(e)}}return n}});var dt="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|"+"header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",vt=/ jQuery\d+="(?:null|\d+)"/g,mt=new RegExp("<(?:"+dt+")[\\s/>]","i"),gt=/^\s+/,yt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bt=/<([\w:]+)/,wt=/\s*$/g,Lt={option:[1,""],legend:[1,"
","
"],area:[1,"",""],param:[1,"",""],thead:[1,"","
"],tr:[2,"","
"],col:[2,"","
"],td:[3,"","
"],_default:w.support.htmlSerialize?[0,"",""]:[1,"X
","
"]},At=pt(o),Ot=At.appendChild(o.createElement("div"));Lt.optgroup=Lt.option;Lt.tbody=Lt.tfoot=Lt.colgroup=Lt.caption=Lt.thead;Lt.th=Lt.td;w.fn.extend({text:function(e){return w.access(this,function(e){return e===t?w.text(this):this.empty().append((this[0]&&this[0].ownerDocument||o).createTextNode(e))},null,e,arguments.length)},append:function(){return this.domManip(arguments,function(e){if(this.nodeType===1||this.nodeType===11||this.nodeType===9){var t=Mt(this,e);t.appendChild(e)}})},prepend:function(){return this.domManip(arguments,function(e){if(this.nodeType===1||this.nodeType===11||this.nodeType===9){var t=Mt(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return this.domManip(arguments,function(e){if(this.parentNode){this.parentNode.insertBefore(e,this)}})},after:function(){return this.domManip(arguments,function(e){if(this.parentNode){this.parentNode.insertBefore(e,this.nextSibling)}})},remove:function(e,t){var n,r=e?w.filter(e,this):this,i=0;for(;(n=r[i])!=null;i++){if(!t&&n.nodeType===1){w.cleanData(jt(n))}if(n.parentNode){if(t&&w.contains(n.ownerDocument,n)){Pt(jt(n,"script"))}n.parentNode.removeChild(n)}}return this},empty:function(){var e,t=0;for(;(e=this[t])!=null;t++){if(e.nodeType===1){w.cleanData(jt(e,false))}while(e.firstChild){e.removeChild(e.firstChild)}if(e.options&&w.nodeName(e,"select")){e.options.length=0}}return this},clone:function(e,t){e=e==null?false:e;t=t==null?e:t;return this.map(function(){return w.clone(this,e,t)})},html:function(e){return w.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t){return n.nodeType===1?n.innerHTML.replace(vt,""):t}if(typeof e==="string"&&!St.test(e)&&(w.support.htmlSerialize||!mt.test(e))&&(w.support.leadingWhitespace||!gt.test(e))&&!Lt[(bt.exec(e)||["",""])[1].toLowerCase()]){e=e.replace(yt,"<$1>");try{for(;r")){s=e.cloneNode(true)}else{Ot.innerHTML=e.outerHTML;Ot.removeChild(s=Ot.firstChild)}if((!w.support.noCloneEvent||!w.support.noCloneChecked)&&(e.nodeType===1||e.nodeType===11)&&!w.isXMLDoc(e)){r=jt(s);u=jt(e);for(o=0;(i=u[o])!=null;++o){if(r[o]){Bt(i,r[o])}}}if(t){if(n){u=u||jt(e);r=r||jt(s);for(o=0;(i=u[o])!=null;o++){Ht(i,r[o])}}else{Ht(e,s)}}r=jt(s,"script");if(r.length>0){Pt(r,!a&&jt(e,"script"))}r=u=i=null;return s},buildFragment:function(e,t,n,r){var i,s,o,u,a,f,l,c=e.length,h=pt(t),p=[],d=0;for(;d")+l[2];i=l[0];while(i--){u=u.lastChild}if(!w.support.leadingWhitespace&>.test(s)){p.push(t.createTextNode(gt.exec(s)[0]))}if(!w.support.tbody){s=a==="table"&&!wt.test(s)?u.firstChild:l[1]===""&&!wt.test(s)?u:0;i=s&&s.childNodes.length;while(i--){if(w.nodeName(f=s.childNodes[i],"tbody")&&!f.childNodes.length){s.removeChild(f)}}}w.merge(p,u.childNodes);u.textContent="";while(u.firstChild){u.removeChild(u.firstChild)}u=h.lastChild}}}if(u){h.removeChild(u)}if(!w.support.appendChecked){w.grep(jt(p,"input"),Ft)}d=0;while(s=p[d++]){if(r&&w.inArray(s,r)!==-1){continue}o=w.contains(s.ownerDocument,s);u=jt(h.appendChild(s),"script");if(o){Pt(u)}if(n){i=0;while(s=u[i++]){if(Nt.test(s.type||"")){n.push(s)}}}}u=null;return h},cleanData:function(e,t){var n,r,s,o,u=0,a=w.expando,f=w.cache,l=w.support.deleteExpando,h=w.event.special;for(;(n=e[u])!=null;u++){if(t||w.acceptData(n)){s=n[a];o=s&&f[s];if(o){if(o.events){for(r in o.events){if(h[r]){w.event.remove(n,r)}else{w.removeEvent(n,r,o.handle)}}}if(f[s]){delete f[s];if(l){delete n[a]}else if(typeof n.removeAttribute!==i){n.removeAttribute(a)}else{n[a]=null}c.push(s)}}}}},_evalUrl:function(e){return w.ajax({url:e,type:"GET",dataType:"script",async:false,global:false,"throws":true})}});w.fn.extend({wrapAll:function(e){if(w.isFunction(e)){return this.each(function(t){w(this).wrapAll(e.call(this,t))})}if(this[0]){var t=w(e,this[0].ownerDocument).eq(0).clone(true);if(this[0].parentNode){t.insertBefore(this[0])}t.map(function(){var e=this;while(e.firstChild&&e.firstChild.nodeType===1){e=e.firstChild}return e}).append(this)}return this},wrapInner:function(e){if(w.isFunction(e)){return this.each(function(t){w(this).wrapInner(e.call(this,t))})}return this.each(function(){var t=w(this),n=t.contents();if(n.length){n.wrapAll(e)}else{t.append(e)}})},wrap:function(e){var t=w.isFunction(e);return this.each(function(n){w(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){if(!w.nodeName(this,"body")){w(this).replaceWith(this.childNodes)}}).end()}});var It,qt,Rt,Ut=/alpha\([^)]*\)/i,zt=/opacity\s*=\s*([^)]*)/,Wt=/^(top|right|bottom|left)$/,Xt=/^(none|table(?!-c[ea]).+)/,Vt=/^margin/,$t=new RegExp("^("+E+")(.*)$","i"),Jt=new RegExp("^("+E+")(?!px)[a-z%]+$","i"),Kt=new RegExp("^([+-])=("+E+")","i"),Qt={BODY:"block"},Gt={position:"absolute",visibility:"hidden",display:"block"},Yt={letterSpacing:0,fontWeight:400},Zt=["Top","Right","Bottom","Left"],en=["Webkit","O","Moz","ms"];w.fn.extend({css:function(e,n){return w.access(this,function(e,n,r){var i,s,o={},u=0;if(w.isArray(n)){s=qt(e);i=n.length;for(;u1)},show:function(){return rn(this,true)},hide:function(){return rn(this)},toggle:function(e){if(typeof e==="boolean"){return e?this.show():this.hide()}return this.each(function(){if(nn(this)){w(this).show()}else{w(this).hide()}})}});w.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Rt(e,"opacity");return n===""?"1":n}}}},cssNumber:{columnCount:true,fillOpacity:true,fontWeight:true,lineHeight:true,opacity:true,order:true,orphans:true,widows:true,zIndex:true,zoom:true},cssProps:{"float":w.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(!e||e.nodeType===3||e.nodeType===8||!e.style){return}var s,o,u,a=w.camelCase(n),f=e.style;n=w.cssProps[a]||(w.cssProps[a]=tn(f,a));u=w.cssHooks[n]||w.cssHooks[a];if(r!==t){o=typeof r;if(o==="string"&&(s=Kt.exec(r))){r=(s[1]+1)*s[2]+parseFloat(w.css(e,n));o="number"}if(r==null||o==="number"&&isNaN(r)){return}if(o==="number"&&!w.cssNumber[a]){r+="px"}if(!w.support.clearCloneStyle&&r===""&&n.indexOf("background")===0){f[n]="inherit"}if(!u||!("set"in u)||(r=u.set(e,r,i))!==t){try{f[n]=r}catch(l){}}}else{if(u&&"get"in u&&(s=u.get(e,false,i))!==t){return s}return f[n]}},css:function(e,n,r,i){var s,o,u,a=w.camelCase(n);n=w.cssProps[a]||(w.cssProps[a]=tn(e.style,a));u=w.cssHooks[n]||w.cssHooks[a];if(u&&"get"in u){o=u.get(e,true,r)}if(o===t){o=Rt(e,n,i)}if(o==="normal"&&n in Yt){o=Yt[n]}if(r===""||r){s=parseFloat(o);return r===true||w.isNumeric(s)?s||0:o}return o}});if(e.getComputedStyle){qt=function(t){return e.getComputedStyle(t,null)};Rt=function(e,n,r){var i,s,o,u=r||qt(e),a=u?u.getPropertyValue(n)||u[n]:t,f=e.style;if(u){if(a===""&&!w.contains(e.ownerDocument,e)){a=w.style(e,n)}if(Jt.test(a)&&Vt.test(n)){i=f.width;s=f.minWidth;o=f.maxWidth;f.minWidth=f.maxWidth=f.width=a;a=u.width;f.width=i;f.minWidth=s;f.maxWidth=o}}return a}}else if(o.documentElement.currentStyle){qt=function(e){return e.currentStyle};Rt=function(e,n,r){var i,s,o,u=r||qt(e),a=u?u[n]:t,f=e.style;if(a==null&&f&&f[n]){a=f[n]}if(Jt.test(a)&&!Wt.test(n)){i=f.left;s=e.runtimeStyle;o=s&&s.left;if(o){s.left=e.currentStyle.left}f.left=n==="fontSize"?"1em":a;a=f.pixelLeft+"px";f.left=i;if(o){s.left=o}}return a===""?"auto":a}}w.each(["height","width"],function(e,t){w.cssHooks[t]={get:function(e,n,r){if(n){return e.offsetWidth===0&&Xt.test(w.css(e,"display"))?w.swap(e,Gt,function(){return un(e,t,r)}):un(e,t,r)}},set:function(e,n,r){var i=r&&qt(e);return sn(e,n,r?on(e,t,r,w.support.boxSizing&&w.css(e,"boxSizing",false,i)==="border-box",i):0)}}});if(!w.support.opacity){w.cssHooks.opacity={get:function(e,t){return zt.test((t&&e.currentStyle?e.currentStyle.filter:e.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":t?"1":""},set:function(e,t){var n=e.style,r=e.currentStyle,i=w.isNumeric(t)?"alpha(opacity="+t*100+")":"",s=r&&r.filter||n.filter||"";n.zoom=1;if((t>=1||t==="")&&w.trim(s.replace(Ut,""))===""&&n.removeAttribute){n.removeAttribute("filter");if(t===""||r&&!r.filter){return}}n.filter=Ut.test(s)?s.replace(Ut,i):s+" "+i}}}w(function(){if(!w.support.reliableMarginRight){w.cssHooks.marginRight={get:function(e,t){if(t){return w.swap(e,{display:"inline-block"},Rt,[e,"marginRight"])}}}}if(!w.support.pixelPosition&&w.fn.position){w.each(["top","left"],function(e,t){w.cssHooks[t]={get:function(e,n){if(n){n=Rt(e,t);return Jt.test(n)?w(e).position()[t]+"px":n}}}})}});if(w.expr&&w.expr.filters){w.expr.filters.hidden=function(e){return e.offsetWidth<=0&&e.offsetHeight<=0||!w.support.reliableHiddenOffsets&&(e.style&&e.style.display||w.css(e,"display"))==="none"};w.expr.filters.visible=function(e){return!w.expr.filters.hidden(e)}}w.each({margin:"",padding:"",border:"Width"},function(e,t){w.cssHooks[e+t]={expand:function(n){var r=0,i={},s=typeof n==="string"?n.split(" "):[n];for(;r<4;r++){i[e+Zt[r]+t]=s[r]||s[r-2]||s[0]}return i}};if(!Vt.test(e)){w.cssHooks[e+t].set=sn}});var ln=/%20/g,cn=/\[\]$/,hn=/\r?\n/g,pn=/^(?:submit|button|image|reset|file)$/i,dn=/^(?:input|select|textarea|keygen)/i;w.fn.extend({serialize:function(){return w.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=w.prop(this,"elements");return e?w.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!w(this).is(":disabled")&&dn.test(this.nodeName)&&!pn.test(e)&&(this.checked||!xt.test(e))}).map(function(e,t){var n=w(this).val();return n==null?null:w.isArray(n)?w.map(n,function(e){return{name:t.name,value:e.replace(hn,"\r\n")}}):{name:t.name,value:n.replace(hn,"\r\n")}}).get()}});w.param=function(e,n){var r,i=[],s=function(e,t){t=w.isFunction(t)?t():t==null?"":t;i[i.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};if(n===t){n=w.ajaxSettings&&w.ajaxSettings.traditional}if(w.isArray(e)||e.jquery&&!w.isPlainObject(e)){w.each(e,function(){s(this.name,this.value)})}else{for(r in e){vn(r,e[r],n,s)}}return i.join("&").replace(ln,"+")};w.each(("blur focus focusin focusout load resize scroll unload click dblclick "+"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave "+"change select submit keydown keypress keyup error contextmenu").split(" "),function(e,t){w.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}});w.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)},bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return arguments.length===1?this.off(e,"**"):this.off(t,e||"**",n)}});var mn,gn,yn=w.now(),bn=/\?/,wn=/#.*$/,En=/([?&])_=[^&]*/,Sn=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,xn=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Tn=/^(?:GET|HEAD)$/,Nn=/^\/\//,Cn=/^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,kn=w.fn.load,Ln={},An={},On="*/".concat("*");try{gn=s.href}catch(Mn){gn=o.createElement("a");gn.href="";gn=gn.href}mn=Cn.exec(gn.toLowerCase())||[];w.fn.load=function(e,n,r){if(typeof e!=="string"&&kn){return kn.apply(this,arguments)}var i,s,o,u=this,a=e.indexOf(" ");if(a>=0){i=e.slice(a,e.length);e=e.slice(0,a)}if(w.isFunction(n)){r=n;n=t}else if(n&&typeof n==="object"){o="POST"}if(u.length>0){w.ajax({url:e,type:o,dataType:"html",data:n}).done(function(e){s=arguments;u.html(i?w("
").append(w.parseHTML(e)).find(i):e)}).complete(r&&function(e,t){u.each(r,s||[e.responseText,t,e])})}return this};w.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){w.fn[t]=function(e){return this.on(t,e)}});w.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:gn,type:"GET",isLocal:xn.test(mn[1]),global:true,processData:true,async:true,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":On,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":true,"text json":w.parseJSON,"text xml":w.parseXML},flatOptions:{url:true,context:true}},ajaxSetup:function(e,t){return t?Pn(Pn(e,w.ajaxSettings),t):Pn(w.ajaxSettings,e)},ajaxPrefilter:_n(Ln),ajaxTransport:_n(An),ajax:function(e,n){function N(e,n,r,i){var l,g,y,E,S,T=n;if(b===2){return}b=2;if(u){clearTimeout(u)}f=t;o=i||"";x.readyState=e>0?4:0;l=e>=200&&e<300||e===304;if(r){E=Hn(c,x,r)}E=Bn(c,E,x,l);if(l){if(c.ifModified){S=x.getResponseHeader("Last-Modified");if(S){w.lastModified[s]=S}S=x.getResponseHeader("etag");if(S){w.etag[s]=S}}if(e===204||c.type==="HEAD"){T="nocontent"}else if(e===304){T="notmodified"}else{T=E.state;g=E.data;y=E.error;l=!y}}else{y=T;if(e||!T){T="error";if(e<0){e=0}}}x.status=e;x.statusText=(n||T)+"";if(l){d.resolveWith(h,[g,T,x])}else{d.rejectWith(h,[x,T,y])}x.statusCode(m);m=t;if(a){p.trigger(l?"ajaxSuccess":"ajaxError",[x,c,l?g:y])}v.fireWith(h,[x,T]);if(a){p.trigger("ajaxComplete",[x,c]);if(!--w.active){w.event.trigger("ajaxStop")}}}if(typeof e==="object"){n=e;e=t}n=n||{};var r,i,s,o,u,a,f,l,c=w.ajaxSetup({},n),h=c.context||c,p=c.context&&(h.nodeType||h.jquery)?w(h):w.event,d=w.Deferred(),v=w.Callbacks("once memory"),m=c.statusCode||{},g={},y={},b=0,E="canceled",x={readyState:0,getResponseHeader:function(e){var t;if(b===2){if(!l){l={};while(t=Sn.exec(o)){l[t[1].toLowerCase()]=t[2]}}t=l[e.toLowerCase()]}return t==null?null:t},getAllResponseHeaders:function(){return b===2?o:null},setRequestHeader:function(e,t){var n=e.toLowerCase();if(!b){e=y[n]=y[n]||e;g[e]=t}return this},overrideMimeType:function(e){if(!b){c.mimeType=e}return this},statusCode:function(e){var t;if(e){if(b<2){for(t in e){m[t]=[m[t],e[t]]}}else{x.always(e[x.status])}}return this},abort:function(e){var t=e||E;if(f){f.abort(t)}N(0,t);return this}};d.promise(x).complete=v.add;x.success=x.done;x.error=x.fail;c.url=((e||c.url||gn)+"").replace(wn,"").replace(Nn,mn[1]+"//");c.type=n.method||n.type||c.method||c.type;c.dataTypes=w.trim(c.dataType||"*").toLowerCase().match(S)||[""];if(c.crossDomain==null){r=Cn.exec(c.url.toLowerCase());c.crossDomain=!!(r&&(r[1]!==mn[1]||r[2]!==mn[2]||(r[3]||(r[1]==="http:"?"80":"443"))!==(mn[3]||(mn[1]==="http:"?"80":"443"))))}if(c.data&&c.processData&&typeof c.data!=="string"){c.data=w.param(c.data,c.traditional)}Dn(Ln,c,n,x);if(b===2){return x}a=c.global;if(a&&w.active++===0){w.event.trigger("ajaxStart")}c.type=c.type.toUpperCase();c.hasContent=!Tn.test(c.type);s=c.url;if(!c.hasContent){if(c.data){s=c.url+=(bn.test(s)?"&":"?")+c.data;delete c.data}if(c.cache===false){c.url=En.test(s)?s.replace(En,"$1_="+yn++):s+(bn.test(s)?"&":"?")+"_="+yn++}}if(c.ifModified){if(w.lastModified[s]){x.setRequestHeader("If-Modified-Since",w.lastModified[s])}if(w.etag[s]){x.setRequestHeader("If-None-Match",w.etag[s])}}if(c.data&&c.hasContent&&c.contentType!==false||n.contentType){x.setRequestHeader("Content-Type",c.contentType)}x.setRequestHeader("Accept",c.dataTypes[0]&&c.accepts[c.dataTypes[0]]?c.accepts[c.dataTypes[0]]+(c.dataTypes[0]!=="*"?", "+On+"; q=0.01":""):c.accepts["*"]);for(i in c.headers){x.setRequestHeader(i,c.headers[i])}if(c.beforeSend&&(c.beforeSend.call(h,x,c)===false||b===2)){return x.abort()}E="abort";for(i in{success:1,error:1,complete:1}){x[i](c[i])}f=Dn(An,c,n,x);if(!f){N(-1,"No Transport")}else{x.readyState=1;if(a){p.trigger("ajaxSend",[x,c])}if(c.async&&c.timeout>0){u=setTimeout(function(){x.abort("timeout")},c.timeout)}try{b=1;f.send(g,N)}catch(T){if(b<2){N(-1,T)}else{throw T}}}return x},getJSON:function(e,t,n){return w.get(e,t,n,"json")},getScript:function(e,n){return w.get(e,t,n,"script")}});w.each(["get","post"],function(e,n){w[n]=function(e,r,i,s){if(w.isFunction(r)){s=s||i;i=r;r=t}return w.ajax({url:e,type:n,dataType:s,data:r,success:i})}});w.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(e){w.globalEval(e);return e}}});w.ajaxPrefilter("script",function(e){if(e.cache===t){e.cache=false}if(e.crossDomain){e.type="GET";e.global=false}});w.ajaxTransport("script",function(e){if(e.crossDomain){var n,r=o.head||w("head")[0]||o.documentElement;return{send:function(t,i){n=o.createElement("script");n.async=true;if(e.scriptCharset){n.charset=e.scriptCharset}n.src=e.url;n.onload=n.onreadystatechange=function(e,t){if(t||!n.readyState||/loaded|complete/.test(n.readyState)){n.onload=n.onreadystatechange=null;if(n.parentNode){n.parentNode.removeChild(n)}n=null;if(!t){i(200,"success")}}};r.insertBefore(n,r.firstChild)},abort:function(){if(n){n.onload(t,true)}}}}});var jn=[],Fn=/(=)\?(?=&|$)|\?\?/;w.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=jn.pop()||w.expando+"_"+yn++;this[e]=true;return e}});w.ajaxPrefilter("json jsonp",function(n,r,i){var s,o,u,a=n.jsonp!==false&&(Fn.test(n.url)?"url":typeof n.data==="string"&&!(n.contentType||"").indexOf("application/x-www-form-urlencoded")&&Fn.test(n.data)&&"data");if(a||n.dataTypes[0]==="jsonp"){s=n.jsonpCallback=w.isFunction(n.jsonpCallback)?n.jsonpCallback():n.jsonpCallback;if(a){n[a]=n[a].replace(Fn,"$1"+s)}else if(n.jsonp!==false){n.url+=(bn.test(n.url)?"&":"?")+n.jsonp+"="+s}n.converters["script json"]=function(){if(!u){w.error(s+" was not called")}return u[0]};n.dataTypes[0]="json";o=e[s];e[s]=function(){u=arguments};i.always(function(){e[s]=o;if(n[s]){n.jsonpCallback=r.jsonpCallback;jn.push(s)}if(u&&w.isFunction(o)){o(u[0])}u=o=t});return"script"}});var In,qn,Rn=0,Un=e.ActiveXObject&&function(){var e;for(e in In){In[e](t,true)}};w.ajaxSettings.xhr=e.ActiveXObject?function(){return!this.isLocal&&zn()||Wn()}:zn;qn=w.ajaxSettings.xhr();w.support.cors=!!qn&&"withCredentials"in qn;qn=w.support.ajax=!!qn;if(qn){w.ajaxTransport(function(n){if(!n.crossDomain||w.support.cors){var r;return{send:function(i,s){var o,u,a=n.xhr();if(n.username){a.open(n.type,n.url,n.async,n.username,n.password)}else{a.open(n.type,n.url,n.async)}if(n.xhrFields){for(u in n.xhrFields){a[u]=n.xhrFields[u]}}if(n.mimeType&&a.overrideMimeType){a.overrideMimeType(n.mimeType)}if(!n.crossDomain&&!i["X-Requested-With"]){i["X-Requested-With"]="XMLHttpRequest"}try{for(u in i){a.setRequestHeader(u,i[u])}}catch(f){}a.send(n.hasContent&&n.data||null);r=function(e,i){var u,f,l,c;try{if(r&&(i||a.readyState===4)){r=t;if(o){a.onreadystatechange=w.noop;if(Un){delete In[o]}}if(i){if(a.readyState!==4){a.abort()}}else{c={};u=a.status;f=a.getAllResponseHeaders();if(typeof a.responseText==="string"){c.text=a.responseText}try{l=a.statusText}catch(h){l=""}if(!u&&n.isLocal&&!n.crossDomain){u=c.text?200:404}else if(u===1223){u=204}}}}catch(p){if(!i){s(-1,p)}}if(c){s(u,l,c,f)}};if(!n.async){r()}else if(a.readyState===4){setTimeout(r)}else{o=++Rn;if(Un){if(!In){In={};w(e).unload(Un)}In[o]=r}a.onreadystatechange=r}},abort:function(){if(r){r(t,true)}}}}})}var Xn,Vn,$n=/^(?:toggle|show|hide)$/,Jn=new RegExp("^(?:([+-])=|)("+E+")([a-z%]*)$","i"),Kn=/queueHooks$/,Qn=[nr],Gn={"*":[function(e,t){var n=this.createTween(e,t),r=n.cur(),i=Jn.exec(t),s=i&&i[3]||(w.cssNumber[e]?"":"px"),o=(w.cssNumber[e]||s!=="px"&&+r)&&Jn.exec(w.css(n.elem,e)),u=1,a=20;if(o&&o[3]!==s){s=s||o[3];i=i||[];o=+r||1;do{u=u||".5";o=o/u;w.style(n.elem,e,o+s)}while(u!==(u=n.cur()/r)&&u!==1&&--a)}if(i){o=n.start=+o||+r||0;n.unit=s;n.end=i[1]?o+(i[1]+1)*i[2]:+i[2]}return n}]};w.Animation=w.extend(er,{tweener:function(e,t){if(w.isFunction(e)){t=e;e=["*"]}else{e=e.split(" ")}var n,r=0,i=e.length;for(;r-1,f={},l={},c,h;if(a){l=i.position();c=l.top;h=l.left}else{c=parseFloat(o)||0;h=parseFloat(u)||0}if(w.isFunction(t)){t=t.call(e,n,s)}if(t.top!=null){f.top=t.top-s.top+c}if(t.left!=null){f.left=t.left-s.left+h}if("using"in t){t.using.call(e,f)}else{i.css(f)}}};w.fn.extend({position:function(){if(!this[0]){return}var e,t,n={top:0,left:0},r=this[0];if(w.css(r,"position")==="fixed"){t=r.getBoundingClientRect()}else{e=this.offsetParent();t=this.offset();if(!w.nodeName(e[0],"html")){n=e.offset()}n.top+=w.css(e[0],"borderTopWidth",true);n.left+=w.css(e[0],"borderLeftWidth",true)}return{top:t.top-n.top-w.css(r,"marginTop",true),left:t.left-n.left-w.css(r,"marginLeft",true)}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||u;while(e&&!w.nodeName(e,"html")&&w.css(e,"position")==="static"){e=e.offsetParent}return e||u})}});w.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,n){var r=/Y/.test(n);w.fn[e]=function(i){return w.access(this,function(e,i,s){var o=sr(e);if(s===t){return o?n in o?o[n]:o.document.documentElement[i]:e[i]}if(o){o.scrollTo(!r?s:w(o).scrollLeft(),r?s:w(o).scrollTop())}else{e[i]=s}},e,i,arguments.length,null)}});w.each({Height:"height",Width:"width"},function(e,n){w.each({padding:"inner"+e,content:n,"":"outer"+e},function(r,i){w.fn[i]=function(i,s){var o=arguments.length&&(r||typeof i!=="boolean"),u=r||(i===true||s===true?"margin":"border");return w.access(this,function(n,r,i){var s;if(w.isWindow(n)){return n.document.documentElement["client"+e]}if(n.nodeType===9){s=n.documentElement;return Math.max(n.body["scroll"+e],s["scroll"+e],n.body["offset"+e],s["offset"+e],s["client"+e])}return i===t?w.css(n,r,u):w.style(n,r,i,u)},n,o?i:t,o,null)}})});w.fn.size=function(){return this.length};w.fn.andSelf=w.fn.addBack;if(typeof module==="object"&&module&&typeof module.exports==="object"){module.exports=w}else{e.jQuery=e.$=w;if(typeof define==="function"&&define.amd){define("jquery",[],function(){return w})}}})(window);jQuery.fn.extend({everyTime:function(e,t,n,r){return this.each(function(){jQuery.timer.add(this,e,t,n,r)})},oneTime:function(e,t,n){return this.each(function(){jQuery.timer.add(this,e,t,n,1)})},stopTime:function(e,t){return this.each(function(){jQuery.timer.remove(this,e,t)})}});jQuery.extend({timer:{global:[],guid:1,dataKey:"jQuery.timer",regex:/^([0-9]+(?:\.[0-9]*)?)\s*(.*s)?$/,powers:{ms:1,cs:10,ds:100,s:1e3,das:1e4,hs:1e5,ks:1e6},timeParse:function(e){if(e==undefined||e==null)return null;var t=this.regex.exec(jQuery.trim(e.toString()));return t[2]?parseFloat(t[1])*(this.powers[t[2]]||1):e},add:function(e,t,n,r,i){var s=0;if(jQuery.isFunction(n)){i||(i=r);r=n;n=t}t=jQuery.timer.timeParse(t);if(!(typeof t!="number"||isNaN(t)||t<0)){if(typeof i!="number"||isNaN(i)||i<0)i=0;i=i||0;var o=jQuery.data(e,this.dataKey)||jQuery.data(e,this.dataKey,{});o[n]||(o[n]={});r.timerID=r.timerID||this.guid++;var u=function(){if(++s>i&&i!==0||r.call(e,s)===false)jQuery.timer.remove(e,n,r)};u.timerID=r.timerID;o[n][r.timerID]||(o[n][r.timerID]=window.setInterval(u,t));this.global.push(e)}},remove:function(e,t,n){var r=jQuery.data(e,this.dataKey),i;if(r){if(t){if(r[t]){if(n){if(n.timerID){window.clearInterval(r[t][n.timerID]);delete r[t][n.timerID]}}else for(n in r[t]){window.clearInterval(r[t][n]);delete r[t][n]}for(i in r[t])break;if(!i){i=null;delete r[t]}}}else for(t in r)this.remove(e,t,n);for(i in r)break;i||jQuery.removeData(e,this.dataKey)}}}});jQuery(window).bind("unload",function(){jQuery.each(jQuery.timer.global,function(e,t){jQuery.timer.remove(t)})});(function(){"use strict";function encodeHTMLSource(){var e={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"},t=/&(?!#?\w+;)|<|>|"|'|\//g;return function(){return this?this.replace(t,function(t){return e[t]||t}):this}}function resolveDefs(e,t,n){return(typeof t==="string"?t:t.toString()).replace(e.define||skip,function(t,r,i,s){if(r.indexOf("def.")===0){r=r.substring(4)}if(!(r in n)){if(i===":"){if(e.defineParams)s.replace(e.defineParams,function(e,t,i){n[r]={arg:t,text:i}});if(!(r in n))n[r]=s}else{(new Function("def","def['"+r+"']="+s))(n)}}return""}).replace(e.use||skip,function(t,r){if(e.useParams)r=r.replace(e.useParams,function(e,t,r,i){if(n[r]&&n[r].arg&&i){var s=(r+":"+i).replace(/'|\\/g,"_");n.__exp=n.__exp||{};n.__exp[s]=n[r].text.replace(new RegExp("(^|[^\\w$])"+n[r].arg+"([^\\w$])","g"),"$1"+i+"$2");return t+"def.__exp['"+s+"']"}});var i=(new Function("def","return "+r))(n);return i?resolveDefs(e,i,n):i})}function unescape(e){return e.replace(/\\('|\\)/g,"$1").replace(/[\r\t\n]/g," ")}var doT={version:"1.0.1-nanoui",templateSettings:{evaluate:/\{\{([\s\S]+?)\}\}/g,interpolate:/\{\{:([\s\S]+?)\}\}/g,encode:/\{\{>([\s\S]+?)\}\}/g,use:/\{\{#([\s\S]+?)\}\}/g,define:/\{\{##\s*([\w\.$]+)\s*(\:|=)([\s\S]+?)#\}\}/g,conditional:/\{\{\/?if\s*([\s\S]*?)\s*\}\}/g,conditionalElse:/\{\{else\s*([\s\S]*?)\s*\}\}/g,iterate:/\{\{\/?for\s*(?:\}\}|([\s\S]+?)\s*(?:\:\s*([\w$]+))?\s*(?:\:\s*([\w$]+))?\s*\}\})/g,props:/\{\{\/?props\s*(?:\}\}|([\s\S]+?)\s*(?:\:\s*([\w$]+))?\s*(?:\:\s*([\w$]+))?\s*\}\})/g,empty:/\{\{empty\}\}/g,varname:"data, config, helper",strip:true,append:true,selfcontained:false},template:undefined,compile:undefined},global;if(typeof module!=="undefined"&&module.exports){module.exports=doT}else if(typeof define==="function"&&define.amd){define(function(){return doT})}else{global=function(){return this||(0,eval)("this")}();global.doT=doT}String.prototype.encodeHTML=encodeHTMLSource();var startend={append:{start:"'+(",end:")+'",endencode:"||'').toString().encodeHTML()+'"},split:{start:"';out+=(",end:");out+='",endencode:"||'').toString().encodeHTML();out+='"}},skip=/$^/;doT.template=function(e,t,n){t=t||doT.templateSettings;var r=t.append?startend.append:startend.split,i,s=0,o=t.use||t.define?resolveDefs(t,e,n||{}):e;o=("var out='"+(t.strip?o.replace(/(^|\r|\n)\t* +| +\t*(\r|\n|$)/g," ").replace(/\r|\n|\t|\/\*[\s\S]*?\*\//g,""):o).replace(/'|\\/g,"\\$&").replace(t.interpolate||skip,function(e,t){return r.start+unescape(t)+r.end}).replace(t.encode||skip,function(e,t){i=true;return r.start+unescape(t)+r.endencode}).replace(t.conditional||skip,function(e,t){return t?"';if("+unescape(t)+"){out+='":"';}out+='"}).replace(t.conditionalElse||skip,function(e,t){return t?"';}else if("+unescape(t)+"){out+='":"';}else{out+='"}).replace(t.iterate||skip,function(e,t,n,r){if(!t)return"';} } out+='";s+=1;n=n||"value";r=r||"index";t=unescape(t);var i="arr"+s;return"';var "+i+"="+t+";if("+i+" && "+i+".length > 0){var "+n+","+r+"=-1,l"+s+"="+i+".length-1;while("+r+" 0){var "+n+";for( var "+r+" in "+i+"){ if (!"+i+".hasOwnProperty("+r+")) continue; "+n+"="+i+"["+r+"];out+='"}).replace(t.empty||skip,function(e){return"';}}else{if(true){out+='"}).replace(t.evaluate||skip,function(e,t){return"';"+unescape(t)+"out+='"})+"';return out;").replace(/\n/g,"\\n").replace(/\t/g,"\\t").replace(/\r/g,"\\r").replace(/(\s|;|\}|^|\{)out\+='';/g,"$1").replace(/\+''/g,"").replace(/(\s|;|\}|^|\{)out\+=''\+/g,"$1out+=");if(i&&t.selfcontained){o="String.prototype.encodeHTML=("+encodeHTMLSource.toString()+"());"+o}try{return new Function(t.varname,o)}catch(u){if(typeof console!=="undefined")console.log("Could not create a template function: "+o);throw u}};doT.compile=function(e,t){return doT.template(e,null,t)}})();(function(e){if(typeof define==="function"&&define.amd){define(["jquery"],e)}else{e(jQuery)}})(function(e){function t(t,r){var i,s,o,u=t.nodeName.toLowerCase();if("area"===u){i=t.parentNode;s=i.name;if(!t.href||!s||i.nodeName.toLowerCase()!=="map"){return false}o=e("img[usemap=#"+s+"]")[0];return!!o&&n(o)}return(/input|select|textarea|button|object/.test(u)?!t.disabled:"a"===u?t.href||r:r)&&n(t)}function n(t){return e.expr.filters.visible(t)&&!e(t).parents().addBack().filter(function(){return e.css(this,"visibility")==="hidden"}).length}e.ui=e.ui||{};e.extend(e.ui,{version:"1.11.0",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}});e.fn.extend({scrollParent:function(){var t=this.css("position"),n=t==="absolute",r=this.parents().filter(function(){var t=e(this);if(n&&t.css("position")==="static"){return false}return/(auto|scroll)/.test(t.css("overflow")+t.css("overflow-y")+t.css("overflow-x"))}).eq(0);return t==="fixed"||!r.length?e(this[0].ownerDocument||document):r},uniqueId:function(){var e=0;return function(){return this.each(function(){if(!this.id){this.id="ui-id-"+ ++e}})}}(),removeUniqueId:function(){return this.each(function(){if(/^ui-id-\d+$/.test(this.id)){e(this).removeAttr("id")}})}});e.extend(e.expr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(n){return!!e.data(n,t)}}):function(t,n,r){return!!e.data(t,r[3])},focusable:function(n){return t(n,!isNaN(e.attr(n,"tabindex")))},tabbable:function(n){var r=e.attr(n,"tabindex"),i=isNaN(r);return(i||r>=0)&&t(n,!i)}});if(!e("").outerWidth(1).jquery){e.each(["Width","Height"],function(t,n){function o(t,n,i,s){e.each(r,function(){n-=parseFloat(e.css(t,"padding"+this))||0;if(i){n-=parseFloat(e.css(t,"border"+this+"Width"))||0}if(s){n-=parseFloat(e.css(t,"margin"+this))||0}});return n}var r=n==="Width"?["Left","Right"]:["Top","Bottom"],i=n.toLowerCase(),s={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+n]=function(t){if(t===undefined){return s["inner"+n].call(this)}return this.each(function(){e(this).css(i,o(this,t)+"px")})};e.fn["outer"+n]=function(t,r){if(typeof t!=="number"){return s["outer"+n].call(this,t)}return this.each(function(){e(this).css(i,o(this,t,true,r)+"px")})}})}if(!e.fn.addBack){e.fn.addBack=function(e){return this.add(e==null?this.prevObject:this.prevObject.filter(e))}}if(e("").data("a-b","a").removeData("a-b").data("a-b")){e.fn.removeData=function(t){return function(n){if(arguments.length){return t.call(this,e.camelCase(n))}else{return t.call(this)}}}(e.fn.removeData)}e.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase());e.fn.extend({focus:function(t){return function(n,r){return typeof n==="number"?this.each(function(){var t=this;setTimeout(function(){e(t).focus();if(r){r.call(t)}},n)}):t.apply(this,arguments)}}(e.fn.focus),disableSelection:function(){var e="onselectstart"in document.createElement("div")?"selectstart":"mousedown";return function(){return this.bind(e+".ui-disableSelection",function(e){e.preventDefault()})}}(),enableSelection:function(){return this.unbind(".ui-disableSelection")},zIndex:function(t){if(t!==undefined){return this.css("zIndex",t)}if(this.length){var n=e(this[0]),r,i;while(n.length&&n[0]!==document){r=n.css("position");if(r==="absolute"||r==="relative"||r==="fixed"){i=parseInt(n.css("zIndex"),10);if(!isNaN(i)&&i!==0){return i}}n=n.parent()}}return 0}});e.ui.plugin={add:function(t,n,r){var i,s=e.ui[t].prototype;for(i in r){s.plugins[i]=s.plugins[i]||[];s.plugins[i].push([n,r[i]])}},call:function(e,t,n,r){var i,s=e.plugins[t];if(!s){return}if(!r&&(!e.element[0].parentNode||e.element[0].parentNode.nodeType===11)){return}for(i=0;i",options:{disabled:false,create:null},_createWidget:function(t,n){n=e(n||this.defaultElement||this)[0];this.element=e(n);this.uuid=r++;this.eventNamespace="."+this.widgetName+this.uuid;this.options=e.widget.extend({},this.options,this._getCreateOptions(),t);this.bindings=e();this.hoverable=e();this.focusable=e();if(n!==this){e.data(n,this.widgetFullName,this);this._on(true,this.element,{remove:function(e){if(e.target===n){this.destroy()}}});this.document=e(n.style?n.ownerDocument:n.document||n);this.window=e(this.document[0].defaultView||this.document[0].parentWindow)}this._create();this._trigger("create",null,this._getCreateEventData());this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy();this.element.unbind(this.eventNamespace).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName));this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled");this.bindings.unbind(this.eventNamespace);this.hoverable.removeClass("ui-state-hover");this.focusable.removeClass("ui-state-focus")},_destroy:e.noop,widget:function(){return this.element},option:function(t,n){var r=t,i,s,o;if(arguments.length===0){return e.widget.extend({},this.options)}if(typeof t==="string"){r={};i=t.split(".");t=i.shift();if(i.length){s=r[t]=e.widget.extend({},this.options[t]);for(o=0;o=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return true}});(function(){function h(e,t,n){return[parseFloat(e[0])*(l.test(e[0])?t/100:1),parseFloat(e[1])*(l.test(e[1])?n/100:1)]}function p(t,n){return parseInt(e.css(t,n),10)||0}function d(t){var n=t[0];if(n.nodeType===9){return{width:t.width(),height:t.height(),offset:{top:0,left:0}}}if(e.isWindow(n)){return{width:t.width(),height:t.height(),offset:{top:t.scrollTop(),left:t.scrollLeft()}}}if(n.preventDefault){return{width:0,height:0,offset:{top:n.pageY,left:n.pageX}}}return{width:t.outerWidth(),height:t.outerHeight(),offset:t.offset()}}e.ui=e.ui||{};var t,n,r=Math.max,i=Math.abs,s=Math.round,o=/left|center|right/,u=/top|center|bottom/,a=/[\+\-]\d+(\.[\d]+)?%?/,f=/^\w+/,l=/%$/,c=e.fn.position;e.position={scrollbarWidth:function(){if(t!==undefined){return t}var n,r,i=e("
"),s=i.children()[0];e("body").append(i);n=s.offsetWidth;i.css("overflow","scroll");r=s.offsetWidth;if(n===r){r=i[0].clientWidth}i.remove();return t=n-r},getScrollInfo:function(t){var n=t.isWindow||t.isDocument?"":t.element.css("overflow-x"),r=t.isWindow||t.isDocument?"":t.element.css("overflow-y"),i=n==="scroll"||n==="auto"&&t.width0?"right":"center",vertical:u<0?"top":o>0?"bottom":"middle"};if(vr(i(o),i(u))){l.important="horizontal"}else{l.important="vertical"}t.using.call(this,e,l)}}a.offset(e.extend(k,{using:u}))})};e.ui.position={fit:{left:function(e,t){var n=t.within,i=n.isWindow?n.scrollLeft:n.offset.left,s=n.width,o=e.left-t.collisionPosition.marginLeft,u=i-o,a=o+t.collisionWidth-s-i,f;if(t.collisionWidth>s){if(u>0&&a<=0){f=e.left+u+t.collisionWidth-s-i;e.left+=u-f}else if(a>0&&u<=0){e.left=i}else{if(u>a){e.left=i+s-t.collisionWidth}else{e.left=i}}}else if(u>0){e.left+=u}else if(a>0){e.left-=a}else{e.left=r(e.left-o,e.left)}},top:function(e,t){var n=t.within,i=n.isWindow?n.scrollTop:n.offset.top,s=t.within.height,o=e.top-t.collisionPosition.marginTop,u=i-o,a=o+t.collisionHeight-s-i,f;if(t.collisionHeight>s){if(u>0&&a<=0){f=e.top+u+t.collisionHeight-s-i;e.top+=u-f}else if(a>0&&u<=0){e.top=i}else{if(u>a){e.top=i+s-t.collisionHeight}else{e.top=i}}}else if(u>0){e.top+=u}else if(a>0){e.top-=a}else{e.top=r(e.top-o,e.top)}}},flip:{left:function(e,t){var n=t.within,r=n.offset.left+n.scrollLeft,s=n.width,o=n.isWindow?n.scrollLeft:n.offset.left,u=e.left-t.collisionPosition.marginLeft,a=u-o,f=u+t.collisionWidth-s-o,l=t.my[0]==="left"?-t.elemWidth:t.my[0]==="right"?t.elemWidth:0,c=t.at[0]==="left"?t.targetWidth:t.at[0]==="right"?-t.targetWidth:0,h=-2*t.offset[0],p,d;if(a<0){p=e.left+l+c+h+t.collisionWidth-s-r;if(p<0||p0){d=e.left-t.collisionPosition.marginLeft+l+c+h-o;if(d>0||i(d)a&&(v<0||v0){d=e.top-t.collisionPosition.marginTop+c+h+p-o;if(e.top+c+h+p>f&&(d>0||i(d)10&&s<11;t.innerHTML="";r.removeChild(t)})()})();var a=e.ui.position;e.widget("ui.draggable",e.ui.mouse,{version:"1.11.0",widgetEventPrefix:"drag",options:{addClasses:true,appendTo:"parent",axis:false,connectToSortable:false,containment:false,cursor:"auto",cursorAt:false,grid:false,handle:false,helper:"original",iframeFix:false,opacity:false,refreshPositions:false,revert:false,revertDuration:500,scope:"default",scroll:true,scrollSensitivity:20,scrollSpeed:20,snap:false,snapMode:"both",snapTolerance:20,stack:false,zIndex:false,drag:null,start:null,stop:null},_create:function(){if(this.options.helper==="original"&&!/^(?:r|a|f)/.test(this.element.css("position"))){this.element[0].style.position="relative"}if(this.options.addClasses){this.element.addClass("ui-draggable")}if(this.options.disabled){this.element.addClass("ui-draggable-disabled")}this._setHandleClassName();this._mouseInit()},_setOption:function(e,t){this._super(e,t);if(e==="handle"){this._setHandleClassName()}},_destroy:function(){if((this.helper||this.element).is(".ui-draggable-dragging")){this.destroyOnClear=true;return}this.element.removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled");this._removeHandleClassName();this._mouseDestroy()},_mouseCapture:function(t){var n=this.document[0],r=this.options;try{if(n.activeElement&&n.activeElement.nodeName.toLowerCase()!=="body"){e(n.activeElement).blur()}}catch(i){}if(this.helper||r.disabled||e(t.target).closest(".ui-resizable-handle").length>0){return false}this.handle=this._getHandle(t);if(!this.handle){return false}e(r.iframeFix===true?"iframe":r.iframeFix).each(function(){e("
").css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1e3}).css(e(this).offset()).appendTo("body")});return true},_mouseStart:function(t){var n=this.options;this.helper=this._createHelper(t);this.helper.addClass("ui-draggable-dragging");this._cacheHelperProportions();if(e.ui.ddmanager){e.ui.ddmanager.current=this}this._cacheMargins();this.cssPosition=this.helper.css("position");this.scrollParent=this.helper.scrollParent();this.offsetParent=this.helper.offsetParent();this.offsetParentCssPosition=this.offsetParent.css("position");this.offset=this.positionAbs=this.element.offset();this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left};this.offset.scroll=false;e.extend(this.offset,{click:{left:t.pageX-this.offset.left,top:t.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this.position=this._generatePosition(t,false);this.originalPageX=t.pageX;this.originalPageY=t.pageY;n.cursorAt&&this._adjustOffsetFromHelper(n.cursorAt);this._setContainment();if(this._trigger("start",t)===false){this._clear();return false}this._cacheHelperProportions();if(e.ui.ddmanager&&!n.dropBehaviour){e.ui.ddmanager.prepareOffsets(this,t)}this._mouseDrag(t,true);if(e.ui.ddmanager){e.ui.ddmanager.dragStart(this,t)}return true},_mouseDrag:function(t,n){if(this.offsetParentCssPosition==="fixed"){this.offset.parent=this._getParentOffset()}this.position=this._generatePosition(t,true);this.positionAbs=this._convertPositionTo("absolute");if(!n){var r=this._uiHash();if(this._trigger("drag",t,r)===false){this._mouseUp({});return false}this.position=r.position}this.helper[0].style.left=this.position.left+"px";this.helper[0].style.top=this.position.top+"px";if(e.ui.ddmanager){e.ui.ddmanager.drag(this,t)}return false},_mouseStop:function(t){var n=this,r=false;if(e.ui.ddmanager&&!this.options.dropBehaviour){r=e.ui.ddmanager.drop(this,t)}if(this.dropped){r=this.dropped;this.dropped=false}if(this.options.revert==="invalid"&&!r||this.options.revert==="valid"&&r||this.options.revert===true||e.isFunction(this.options.revert)&&this.options.revert.call(this.element,r)){e(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){if(n._trigger("stop",t)!==false){n._clear()}})}else{if(this._trigger("stop",t)!==false){this._clear()}}return false},_mouseUp:function(t){e("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)});if(e.ui.ddmanager){e.ui.ddmanager.dragStop(this,t)}this.element.focus();return e.ui.mouse.prototype._mouseUp.call(this,t)},cancel:function(){if(this.helper.is(".ui-draggable-dragging")){this._mouseUp({})}else{this._clear()}return this},_getHandle:function(t){return this.options.handle?!!e(t.target).closest(this.element.find(this.options.handle)).length:true},_setHandleClassName:function(){this._removeHandleClassName();e(this.options.handle||this.element).addClass("ui-draggable-handle")},_removeHandleClassName:function(){this.element.find(".ui-draggable-handle").addBack().removeClass("ui-draggable-handle")},_createHelper:function(t){var n=this.options,r=e.isFunction(n.helper)?e(n.helper.apply(this.element[0],[t])):n.helper==="clone"?this.element.clone().removeAttr("id"):this.element;if(!r.parents("body").length){r.appendTo(n.appendTo==="parent"?this.element[0].parentNode:n.appendTo)}if(r[0]!==this.element[0]&&!/(fixed|absolute)/.test(r.css("position"))){r.css("position","absolute")}return r},_adjustOffsetFromHelper:function(t){if(typeof t==="string"){t=t.split(" ")}if(e.isArray(t)){t={left:+t[0],top:+t[1]||0}}if("left"in t){this.offset.click.left=t.left+this.margins.left}if("right"in t){this.offset.click.left=this.helperProportions.width-t.right+this.margins.left}if("top"in t){this.offset.click.top=t.top+this.margins.top}if("bottom"in t){this.offset.click.top=this.helperProportions.height-t.bottom+this.margins.top}},_isRootNode:function(e){return/(html|body)/i.test(e.tagName)||e===this.document[0]},_getParentOffset:function(){var t=this.offsetParent.offset(),n=this.document[0];if(this.cssPosition==="absolute"&&this.scrollParent[0]!==n&&e.contains(this.scrollParent[0],this.offsetParent[0])){t.left+=this.scrollParent.scrollLeft();t.top+=this.scrollParent.scrollTop()}if(this._isRootNode(this.offsetParent[0])){t={top:0,left:0}}return{top:t.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:t.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition!=="relative"){return{top:0,left:0}}var e=this.element.position(),t=this._isRootNode(this.scrollParent[0]);return{top:e.top-(parseInt(this.helper.css("top"),10)||0)+(!t?this.scrollParent.scrollTop():0),left:e.left-(parseInt(this.helper.css("left"),10)||0)+(!t?this.scrollParent.scrollLeft():0)}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var t,n,r,i=this.options,s=this.document[0];this.relative_container=null;if(!i.containment){this.containment=null;return}if(i.containment==="window"){this.containment=[e(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,e(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,e(window).scrollLeft()+e(window).width()-this.helperProportions.width-this.margins.left,e(window).scrollTop()+(e(window).height()||s.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];return}if(i.containment==="document"){this.containment=[0,0,e(s).width()-this.helperProportions.width-this.margins.left,(e(s).height()||s.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];return}if(i.containment.constructor===Array){this.containment=i.containment;return}if(i.containment==="parent"){i.containment=this.helper[0].parentNode}n=e(i.containment);r=n[0];if(!r){return}t=n.css("overflow")!=="hidden";this.containment=[(parseInt(n.css("borderLeftWidth"),10)||0)+(parseInt(n.css("paddingLeft"),10)||0),(parseInt(n.css("borderTopWidth"),10)||0)+(parseInt(n.css("paddingTop"),10)||0),(t?Math.max(r.scrollWidth,r.offsetWidth):r.offsetWidth)-(parseInt(n.css("borderRightWidth"),10)||0)-(parseInt(n.css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(t?Math.max(r.scrollHeight,r.offsetHeight):r.offsetHeight)-(parseInt(n.css("borderBottomWidth"),10)||0)-(parseInt(n.css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom];this.relative_container=n},_convertPositionTo:function(e,t){if(!t){t=this.position}var n=e==="absolute"?1:-1,r=this._isRootNode(this.scrollParent[0]);return{top:t.top+this.offset.relative.top*n+this.offset.parent.top*n-(this.cssPosition==="fixed"?-this.offset.scroll.top:r?0:this.offset.scroll.top)*n,left:t.left+this.offset.relative.left*n+this.offset.parent.left*n-(this.cssPosition==="fixed"?-this.offset.scroll.left:r?0:this.offset.scroll.left)*n}},_generatePosition:function(e,t){var n,r,i,s,o=this.options,u=this._isRootNode(this.scrollParent[0]),a=e.pageX,f=e.pageY;if(!u||!this.offset.scroll){this.offset.scroll={top:this.scrollParent.scrollTop(),left:this.scrollParent.scrollLeft()}}if(t){if(this.containment){if(this.relative_container){r=this.relative_container.offset();n=[this.containment[0]+r.left,this.containment[1]+r.top,this.containment[2]+r.left,this.containment[3]+r.top]}else{n=this.containment}if(e.pageX-this.offset.click.leftn[2]){a=n[2]+this.offset.click.left}if(e.pageY-this.offset.click.top>n[3]){f=n[3]+this.offset.click.top}}if(o.grid){i=o.grid[1]?this.originalPageY+Math.round((f-this.originalPageY)/o.grid[1])*o.grid[1]:this.originalPageY;f=n?i-this.offset.click.top>=n[1]||i-this.offset.click.top>n[3]?i:i-this.offset.click.top>=n[1]?i-o.grid[1]:i+o.grid[1]:i;s=o.grid[0]?this.originalPageX+Math.round((a-this.originalPageX)/o.grid[0])*o.grid[0]:this.originalPageX;a=n?s-this.offset.click.left>=n[0]||s-this.offset.click.left>n[2]?s:s-this.offset.click.left>=n[0]?s-o.grid[0]:s+o.grid[0]:s}if(o.axis==="y"){a=this.originalPageX}if(o.axis==="x"){f=this.originalPageY}}return{top:f-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(this.cssPosition==="fixed"?-this.offset.scroll.top:u?0:this.offset.scroll.top),left:a-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(this.cssPosition==="fixed"?-this.offset.scroll.left:u?0:this.offset.scroll.left)}},_clear:function(){this.helper.removeClass("ui-draggable-dragging");if(this.helper[0]!==this.element[0]&&!this.cancelHelperRemoval){this.helper.remove()}this.helper=null;this.cancelHelperRemoval=false;if(this.destroyOnClear){this.destroy()}},_trigger:function(t,n,r){r=r||this._uiHash();e.ui.plugin.call(this,t,[n,r,this],true);if(t==="drag"){this.positionAbs=this._convertPositionTo("absolute")}return e.Widget.prototype._trigger.call(this,t,n,r)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}});e.ui.plugin.add("draggable","connectToSortable",{start:function(t,n,r){var i=r.options,s=e.extend({},n,{item:r.element});r.sortables=[];e(i.connectToSortable).each(function(){var n=e(this).sortable("instance");if(n&&!n.options.disabled){r.sortables.push({instance:n,shouldRevert:n.options.revert});n.refreshPositions();n._trigger("activate",t,s)}})},stop:function(t,n,r){var i=e.extend({},n,{item:r.element});e.each(r.sortables,function(){if(this.instance.isOver){this.instance.isOver=0;r.cancelHelperRemoval=true;this.instance.cancelHelperRemoval=false;if(this.shouldRevert){this.instance.options.revert=this.shouldRevert}this.instance._mouseStop(t);this.instance.options.helper=this.instance.options._helper;if(r.options.helper==="original"){this.instance.currentItem.css({top:"auto",left:"auto"})}}else{this.instance.cancelHelperRemoval=false;this.instance._trigger("deactivate",t,i)}})},drag:function(t,n,r){var i=this;e.each(r.sortables,function(){var s=false,o=this;this.instance.positionAbs=r.positionAbs;this.instance.helperProportions=r.helperProportions;this.instance.offset.click=r.offset.click;if(this.instance._intersectsWith(this.instance.containerCache)){s=true;e.each(r.sortables,function(){this.instance.positionAbs=r.positionAbs;this.instance.helperProportions=r.helperProportions;this.instance.offset.click=r.offset.click;if(this!==o&&this.instance._intersectsWith(this.instance.containerCache)&&e.contains(o.instance.element[0],this.instance.element[0])){s=false}return s})}if(s){if(!this.instance.isOver){this.instance.isOver=1;this.instance.currentItem=e(i).clone().removeAttr("id").appendTo(this.instance.element).data("ui-sortable-item",true);this.instance.options._helper=this.instance.options.helper;this.instance.options.helper=function(){return n.helper[0]};t.target=this.instance.currentItem[0];this.instance._mouseCapture(t,true);this.instance._mouseStart(t,true,true);this.instance.offset.click.top=r.offset.click.top;this.instance.offset.click.left=r.offset.click.left;this.instance.offset.parent.left-=r.offset.parent.left-this.instance.offset.parent.left;this.instance.offset.parent.top-=r.offset.parent.top-this.instance.offset.parent.top;r._trigger("toSortable",t);r.dropped=this.instance.element;r.currentItem=r.element;this.instance.fromOutside=r}if(this.instance.currentItem){this.instance._mouseDrag(t)}}else{if(this.instance.isOver){this.instance.isOver=0;this.instance.cancelHelperRemoval=true;this.instance.options.revert=false;this.instance._trigger("out",t,this.instance._uiHash(this.instance));this.instance._mouseStop(t,true);this.instance.options.helper=this.instance.options._helper;this.instance.currentItem.remove();if(this.instance.placeholder){this.instance.placeholder.remove()}r._trigger("fromSortable",t);r.dropped=false}}})}});e.ui.plugin.add("draggable","cursor",{start:function(t,n,r){var i=e("body"),s=r.options;if(i.css("cursor")){s._cursor=i.css("cursor")}i.css("cursor",s.cursor)},stop:function(t,n,r){var i=r.options;if(i._cursor){e("body").css("cursor",i._cursor)}}});e.ui.plugin.add("draggable","opacity",{start:function(t,n,r){var i=e(n.helper),s=r.options;if(i.css("opacity")){s._opacity=i.css("opacity")}i.css("opacity",s.opacity)},stop:function(t,n,r){var i=r.options;if(i._opacity){e(n.helper).css("opacity",i._opacity)}}});e.ui.plugin.add("draggable","scroll",{start:function(e,t,n){if(n.scrollParent[0]!==n.document[0]&&n.scrollParent[0].tagName!=="HTML"){n.overflowOffset=n.scrollParent.offset()}},drag:function(t,n,r){var i=r.options,s=false,o=r.document[0];if(r.scrollParent[0]!==o&&r.scrollParent[0].tagName!=="HTML"){if(!i.axis||i.axis!=="x"){if(r.overflowOffset.top+r.scrollParent[0].offsetHeight-t.pageY=0;h--){a=r.snapElements[h].left;f=a+r.snapElements[h].width;l=r.snapElements[h].top;c=l+r.snapElements[h].height;if(gf+v||bc+v||!e.contains(r.snapElements[h].item.ownerDocument,r.snapElements[h].item)){if(r.snapElements[h].snapping){r.options.snap.release&&r.options.snap.release.call(r.element,t,e.extend(r._uiHash(),{snapItem:r.snapElements[h].item}))}r.snapElements[h].snapping=false;continue}if(d.snapMode!=="inner"){i=Math.abs(l-b)<=v;s=Math.abs(c-y)<=v;o=Math.abs(a-g)<=v;u=Math.abs(f-m)<=v;if(i){n.position.top=r._convertPositionTo("relative",{top:l-r.helperProportions.height,left:0}).top-r.margins.top}if(s){n.position.top=r._convertPositionTo("relative",{top:c,left:0}).top-r.margins.top}if(o){n.position.left=r._convertPositionTo("relative",{top:0,left:a-r.helperProportions.width}).left-r.margins.left}if(u){n.position.left=r._convertPositionTo("relative",{top:0,left:f}).left-r.margins.left}}p=i||s||o||u;if(d.snapMode!=="outer"){i=Math.abs(l-y)<=v;s=Math.abs(c-b)<=v;o=Math.abs(a-m)<=v;u=Math.abs(f-g)<=v;if(i){n.position.top=r._convertPositionTo("relative",{top:l,left:0}).top-r.margins.top}if(s){n.position.top=r._convertPositionTo("relative",{top:c-r.helperProportions.height,left:0}).top-r.margins.top}if(o){n.position.left=r._convertPositionTo("relative",{top:0,left:a}).left-r.margins.left}if(u){n.position.left=r._convertPositionTo("relative",{top:0,left:f-r.helperProportions.width}).left-r.margins.left}}if(!r.snapElements[h].snapping&&(i||s||o||u||p)){r.options.snap.snap&&r.options.snap.snap.call(r.element,t,e.extend(r._uiHash(),{snapItem:r.snapElements[h].item}))}r.snapElements[h].snapping=i||s||o||u||p}}});e.ui.plugin.add("draggable","stack",{start:function(t,n,r){var i,s=r.options,o=e.makeArray(e(s.stack)).sort(function(t,n){return(parseInt(e(t).css("zIndex"),10)||0)-(parseInt(e(n).css("zIndex"),10)||0)});if(!o.length){return}i=parseInt(e(o[0]).css("zIndex"),10)||0;e(o).each(function(t){e(this).css("zIndex",i+t)});this.css("zIndex",i+o.length)}});e.ui.plugin.add("draggable","zIndex",{start:function(t,n,r){var i=e(n.helper),s=r.options;if(i.css("zIndex")){s._zIndex=i.css("zIndex")}i.css("zIndex",s.zIndex)},stop:function(t,n,r){var i=r.options;if(i._zIndex){e(n.helper).css("zIndex",i._zIndex)}}});var f=e.ui.draggable}) \ No newline at end of file diff --git a/nano/js/libraries.min.js b/nano/js/libraries.min.js deleted file mode 100644 index a2cbbad8f1..0000000000 --- a/nano/js/libraries.min.js +++ /dev/null @@ -1,50 +0,0 @@ -/*! jQuery v1.11.3 | (c) 2005, 2015 jQuery Foundation, Inc. | jquery.org/license */ -!function(e,t){"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(e,t){function n(e){var t="length"in e&&e.length,n=it.type(e);return"function"===n||it.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||0===t||"number"==typeof t&&t>0&&t-1 in e}function r(e,t,n){if(it.isFunction(t))return it.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return it.grep(e,function(e){return e===t!==n});if("string"==typeof t){if(ft.test(t))return it.filter(t,e,n);t=it.filter(t,e)}return it.grep(e,function(e){return it.inArray(e,t)>=0!==n})}function i(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}function o(e){var t=xt[e]={};return it.each(e.match(bt)||[],function(e,n){t[n]=!0}),t}function a(){ht.addEventListener?(ht.removeEventListener("DOMContentLoaded",s,!1),e.removeEventListener("load",s,!1)):(ht.detachEvent("onreadystatechange",s),e.detachEvent("onload",s))}function s(){(ht.addEventListener||"load"===event.type||"complete"===ht.readyState)&&(a(),it.ready())}function l(e,t,n){if(void 0===n&&1===e.nodeType){var r="data-"+t.replace(Et,"-$1").toLowerCase();if(n=e.getAttribute(r),"string"==typeof n){try{n="true"===n?!0:"false"===n?!1:"null"===n?null:+n+""===n?+n:Nt.test(n)?it.parseJSON(n):n}catch(i){}it.data(e,t,n)}else n=void 0}return n}function u(e){var t;for(t in e)if(("data"!==t||!it.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}function c(e,t,n,r){if(it.acceptData(e)){var i,o,a=it.expando,s=e.nodeType,l=s?it.cache:e,u=s?e[a]:e[a]&&a;if(u&&l[u]&&(r||l[u].data)||void 0!==n||"string"!=typeof t)return u||(u=s?e[a]=J.pop()||it.guid++:a),l[u]||(l[u]=s?{}:{toJSON:it.noop}),("object"==typeof t||"function"==typeof t)&&(r?l[u]=it.extend(l[u],t):l[u].data=it.extend(l[u].data,t)),o=l[u],r||(o.data||(o.data={}),o=o.data),void 0!==n&&(o[it.camelCase(t)]=n),"string"==typeof t?(i=o[t],null==i&&(i=o[it.camelCase(t)])):i=o,i}}function d(e,t,n){if(it.acceptData(e)){var r,i,o=e.nodeType,a=o?it.cache:e,s=o?e[it.expando]:it.expando;if(a[s]){if(t&&(r=n?a[s]:a[s].data)){it.isArray(t)?t=t.concat(it.map(t,it.camelCase)):t in r?t=[t]:(t=it.camelCase(t),t=t in r?[t]:t.split(" ")),i=t.length;for(;i--;)delete r[t[i]];if(n?!u(r):!it.isEmptyObject(r))return}(n||(delete a[s].data,u(a[s])))&&(o?it.cleanData([e],!0):nt.deleteExpando||a!=a.window?delete a[s]:a[s]=null)}}}function f(){return!0}function p(){return!1}function h(){try{return ht.activeElement}catch(e){}}function m(e){var t=Ft.split("|"),n=e.createDocumentFragment();if(n.createElement)for(;t.length;)n.createElement(t.pop());return n}function g(e,t){var n,r,i=0,o=typeof e.getElementsByTagName!==Ct?e.getElementsByTagName(t||"*"):typeof e.querySelectorAll!==Ct?e.querySelectorAll(t||"*"):void 0;if(!o)for(o=[],n=e.childNodes||e;null!=(r=n[i]);i++)!t||it.nodeName(r,t)?o.push(r):it.merge(o,g(r,t));return void 0===t||t&&it.nodeName(e,t)?it.merge([e],o):o}function v(e){jt.test(e.type)&&(e.defaultChecked=e.checked)}function y(e,t){return it.nodeName(e,"table")&&it.nodeName(11!==t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function b(e){return e.type=(null!==it.find.attr(e,"type"))+"/"+e.type,e}function x(e){var t=Vt.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function w(e,t){for(var n,r=0;null!=(n=e[r]);r++)it._data(n,"globalEval",!t||it._data(t[r],"globalEval"))}function T(e,t){if(1===t.nodeType&&it.hasData(e)){var n,r,i,o=it._data(e),a=it._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)it.event.add(t,n,s[n][r])}a.data&&(a.data=it.extend({},a.data))}}function C(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!nt.noCloneEvent&&t[it.expando]){i=it._data(t);for(r in i.events)it.removeEvent(t,r,i.handle);t.removeAttribute(it.expando)}"script"===n&&t.text!==e.text?(b(t).text=e.text,x(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),nt.html5Clone&&e.innerHTML&&!it.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):"input"===n&&jt.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):"option"===n?t.defaultSelected=t.selected=e.defaultSelected:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}}function N(t,n){var r,i=it(n.createElement(t)).appendTo(n.body),o=e.getDefaultComputedStyle&&(r=e.getDefaultComputedStyle(i[0]))?r.display:it.css(i[0],"display");return i.detach(),o}function E(e){var t=ht,n=Zt[e];return n||(n=N(e,t),"none"!==n&&n||(Kt=(Kt||it("