diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm
index c48a2056572..8370dd40f3c 100644
--- a/code/game/machinery/computer/camera.dm
+++ b/code/game/machinery/computer/camera.dm
@@ -199,6 +199,9 @@
else
if(isAI(user))
var/mob/living/silicon/ai/A = user
+ // Only allow non-carded AIs to view because the interaction with the eye gets all wonky otherwise.
+ if(!A.is_in_chassis())
+ return 0
A.eyeobj.setLoc(get_turf(C))
A.client.eye = A.eyeobj
else
diff --git a/code/game/machinery/computer/computer.dm b/code/game/machinery/computer/computer.dm
index 13fe459ec45..b5e28c3b7a1 100644
--- a/code/game/machinery/computer/computer.dm
+++ b/code/game/machinery/computer/computer.dm
@@ -102,7 +102,19 @@
stat |= BROKEN
update_icon()
+/obj/machinery/computer/proc/decode(text)
+ // Adds line breaks
+ text = replacetext(text, "\n", "
")
+ return text
+
+/obj/machinery/computer/attack_ghost(user as mob)
+ return src.attack_hand(user)
+/obj/machinery/computer/attack_hand(user as mob)
+ /* Observers can view computers, but not actually use them via Topic*/
+ if(istype(user, /mob/dead/observer)) return 0
+ return ..()
+
/obj/machinery/computer/attackby(I as obj, user as mob, params)
if(istype(I, /obj/item/weapon/screwdriver) && circuit)
playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
diff --git a/code/game/machinery/computer/law.dm b/code/game/machinery/computer/law.dm
index 6901f72d63f..4802e855af2 100644
--- a/code/game/machinery/computer/law.dm
+++ b/code/game/machinery/computer/law.dm
@@ -53,7 +53,8 @@
usr << "[src.current.name] selected for law changes."
return
-
+ attack_ghost(user as mob)
+ return 1
/obj/machinery/computer/borgupload
name = "Cyborg Upload"
@@ -85,3 +86,6 @@
else
usr << "[src.current.name] selected for law changes."
return
+
+ attack_ghost(user as mob)
+ return 1
diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm
index 519fb09b0cd..6a0bcbf496f 100644
--- a/code/game/machinery/machinery.dm
+++ b/code/game/machinery/machinery.dm
@@ -184,65 +184,21 @@ Class Procs:
use_power(active_power_usage,power_channel, 1)
return 1
-/obj/machinery/Topic(href, href_list, var/nowindow = 0, var/checkrange = 1)
- if(..())
- return 1
- if(!can_be_used_by(usr, be_close = checkrange))
- return 1
- add_fingerprint(usr)
- return 0
+/obj/machinery/CanUseTopic(var/mob/user, var/be_close)
+ if(!interact_offline && (stat & (NOPOWER|BROKEN)))
+ return STATUS_CLOSE
-/obj/machinery/proc/can_be_used_by(mob/user, be_close = 1)
- if(!interact_offline && stat & (NOPOWER|BROKEN))
- return 0
- if(!user.canUseTopic(src, be_close))
- return 0
- return 1
+ return ..()
+
+/obj/machinery/CouldUseTopic(var/mob/user)
+ ..()
+ user.set_machine(src)
+
+/obj/machinery/CouldNotUseTopic(var/mob/user)
+ usr.unset_machine()
+
+////////////////////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////////////////////
-
-/mob/proc/canUseTopic(atom/movable/M, be_close = 1)
- return
-
-/mob/dead/observer/canUseTopic(atom/movable/M, be_close = 1)
- if(check_rights(R_ADMIN, 0))
- return
-
-/mob/living/canUseTopic(atom/movable/M, be_close = 1, no_dextery = 0)
- if(no_dextery)
- src << "You don't have the dexterity to do this!"
- return 0
- return be_close && !in_range(M, src)
-
-/mob/living/carbon/human/canUseTopic(atom/movable/M, be_close = 1)
- if(restrained() || lying || stat || stunned || weakened)
- return
- if(be_close && !in_range(M, src))
- if(TK in mutations)
- var/mob/living/carbon/human/H = M
- if(istype(H.l_hand, /obj/item/tk_grab) || istype(H.r_hand, /obj/item/tk_grab))
- return 1
- return
- if(!isturf(M.loc) && M.loc != src)
- return
- return 1
-
-/mob/living/silicon/ai/canUseTopic(atom/movable/M)
- if(stat)
- return
- //stop AIs from leaving windows open and using then after they lose vision
- //apc_override is needed here because AIs use their own APC when powerless
- if(cameranet && !cameranet.checkTurfVis(get_turf(M)) && !apc_override)
- return
- return 1
-
-/mob/living/silicon/robot/canUseTopic(atom/movable/M)
- if(stat || lockcharge || stunned || weakened)
- return
- return 1
-
-////////////////////////////////////////////////////////////////////////////////////////////
-
/obj/machinery/attack_ai(var/mob/user as mob)
if(isAI(user))
var/mob/living/silicon/ai/A = user
diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm
index cdab2906826..fa56228cc09 100644
--- a/code/game/machinery/portable_turret.dm
+++ b/code/game/machinery/portable_turret.dm
@@ -155,15 +155,13 @@
qdel(cover) // qdel
..()
-/obj/machinery/porta_turret/proc/isLocked(mob/user,var/message = 1)
+/obj/machinery/porta_turret/proc/isLocked(mob/user)
if(ailock && (isrobot(user) || isAI(user)))
- if(message)
- user << "There seems to be a firewall preventing you from accessing this device."
+ user << "There seems to be a firewall preventing you from accessing this device."
return 1
if(locked && !(isrobot(user) || isAI(user)))
- if(message)
- user << "Access denied."
+ user << "Access denied."
return 1
return 0
@@ -208,20 +206,23 @@
/obj/machinery/porta_turret/proc/HasController()
var/area/A = get_area(src)
return A && A.turret_controls.len > 0
-
-/obj/machinery/porta_turret/Topic(href, href_list, var/nowindow = 0)
- if(..())
- return 1
-
+
+/obj/machinery/porta_turret/CanUseTopic(var/mob/user)
if(HasController())
- usr << "Turrets can only be controlled using the assigned turret controller."
- return 1
+ user << "Turrets can only be controlled using the assigned turret controller."
+ return STATUS_CLOSE
- if(isLocked(usr,0))
- return 1
+ if(isLocked(user))
+ return STATUS_CLOSE
if(!anchored)
usr << "\The [src] has to be secured first!"
+ return STATUS_CLOSE
+
+ return STATUS_INTERACTIVE
+
+/obj/machinery/porta_turret/Topic(href, href_list, var/nowindow = 0)
+ if(..())
return 1
if(href_list["command"] && href_list["value"])
@@ -754,12 +755,12 @@
if(4)
if(isprox(I))
- build_step = 5
if(!user.unEquip(I))
user << "\the [I] is stuck to your hand, you cannot put it in \the [src]"
return
+ build_step = 5
+ del(I) // del
user << "You add the prox sensor to the turret."
- qdel(I) // qdel
return
//attack_hand() removes the gun
diff --git a/code/game/objects/items/devices/uplinks.dm b/code/game/objects/items/devices/uplinks.dm
index 3fce029a056..fc7a294309e 100644
--- a/code/game/objects/items/devices/uplinks.dm
+++ b/code/game/objects/items/devices/uplinks.dm
@@ -103,7 +103,9 @@ var/list/world_uplinks = list()
/obj/item/device/uplink/Topic(href, href_list)
- ..()
+ if(..())
+ return 1
+
if(!active)
return
@@ -152,7 +154,8 @@ var/list/world_uplinks = list()
desc = "There is something wrong if you're examining this."
/obj/item/device/uplink/hidden/Topic(href, href_list)
- ..()
+ if(..())
+ return 1
if(href_list["lock"])
toggle()
usr << browse(null, "window=hidden")
diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm
index 6049d30bd51..168134c6591 100644
--- a/code/game/objects/objs.dm
+++ b/code/game/objects/objs.dm
@@ -21,15 +21,27 @@
// Reagent ID => friendly name
var/list/reagents_to_log=list()
-/obj/Topic(href, href_list, var/nowindow = 0, var/checkrange = 1)
+/obj/Topic(href, href_list, var/nowindow = 0, var/datum/topic_state/custom_state = default_state)
// Calling Topic without a corresponding window open causes runtime errors
if(!nowindow && ..())
return 1
- if(usr.can_interact_with_interface(nano_host(), checkrange) != STATUS_INTERACTIVE)
- return 1
- add_fingerprint(usr)
- return 0
+ // In the far future no checks are made in an overriding Topic() beyond if(..()) return
+ // Instead any such checks are made in CanUseTopic()
+ var/obj/host = nano_host()
+ if(host.CanUseTopic(usr, href_list, custom_state) == STATUS_INTERACTIVE)
+ CouldUseTopic(usr)
+ return 0
+
+ CouldNotUseTopic(usr)
+ return 1
+
+/obj/proc/CouldUseTopic(var/mob/user)
+ var/atom/host = nano_host()
+ host.add_fingerprint(user)
+
+/obj/proc/CouldNotUseTopic(var/mob/user)
+ // Nada
/obj/Destroy()
machines -= src
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index 3775adfba20..9bb0eee9203 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -1484,16 +1484,6 @@ var/list/robot_verbs_default = list(
radio.recalculateChannels()
playsound(loc, 'sound/mecha/nominalsyndi.ogg', 75, 0)
-
-/mob/living/silicon/robot/syndicate/canUseTopic(atom/movable/M)
- if(stat || lockcharge || stunned || weakened)
- return
- if(z in config.admin_levels)
- return 1
- /*if(istype(M, /obj/machinery))
- var/obj/machinery/Machine = M
- return Machine.emagged*/
- return 1
/mob/living/silicon/robot/proc/notify_ai(var/notifytype, var/oldname, var/newname)
if(!connected_ai)
diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm
index cf801fc4311..d306f739835 100644
--- a/code/modules/mob/mob_helpers.dm
+++ b/code/modules/mob/mob_helpers.dm
@@ -114,6 +114,11 @@ proc/isembryo(A)
if(istype(A, /mob/living/silicon))
return 1
return 0
+
+/proc/isSilicon(A) // Bay support
+ if(istype(A, /mob/living/silicon))
+ return 1
+ return 0
/proc/isliving(A)
if(istype(A, /mob/living))
diff --git a/code/modules/nano/nanoexternal.dm b/code/modules/nano/nanoexternal.dm
index 3e5a011d5fa..b029019f1a3 100644
--- a/code/modules/nano/nanoexternal.dm
+++ b/code/modules/nano/nanoexternal.dm
@@ -31,18 +31,13 @@
* ui_interact is currently defined for /atom/movable
*
* @param user /mob The mob who is interacting with this ui
-<<<<<<< HEAD
* @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 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
->>>>>>> 7e7e6cd... Continued work in progress on a major revision of the NanoUI templating system.
*
* @return nothing
*/
-/atom/movable/proc/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
+/atom/movable/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/custom_state = null)
return
// Used by the Nano UI Manager (/datum/nanomanager) to track UIs opened by this mob
diff --git a/code/modules/nano/nanointeraction.dm b/code/modules/nano/nanointeraction.dm
new file mode 100644
index 00000000000..d746c64d689
--- /dev/null
+++ b/code/modules/nano/nanointeraction.dm
@@ -0,0 +1,120 @@
+/atom/movable/proc/nano_host()
+ return src
+
+/obj/nano_module/nano_host()
+ return loc
+
+
+/atom/movable/proc/CanUseTopic(var/mob/user, href_list, var/datum/topic_state/custom_state)
+ return user.can_use_topic(nano_host(), custom_state)
+
+
+/mob/proc/can_use_topic(var/mob/user, var/datum/topic_state/custom_state)
+ return STATUS_CLOSE // By default no mob can do anything with NanoUI
+
+/mob/dead/observer/can_use_topic()
+ if(check_rights(R_ADMIN, 0))
+ return STATUS_INTERACTIVE // Admins are more equal
+ return STATUS_UPDATE // Ghosts can view updates
+
+/mob/living/silicon/pai/can_use_topic(var/src_object)
+ if(src_object == src && !stat)
+ return STATUS_INTERACTIVE
+ else
+ return ..()
+
+/mob/living/silicon/robot/can_use_topic(var/src_object, var/datum/topic_state/custom_state)
+ if(stat || !client)
+ return STATUS_CLOSE
+ if(lockcharge || stunned || weakened)
+ return STATUS_DISABLED
+ // robots can interact with things they can see within their view range
+ if(!(custom_state.flags & NANO_IGNORE_DISTANCE) && (src_object in view(src)))
+ return STATUS_INTERACTIVE // interactive (green visibility)
+ return STATUS_DISABLED // no updates, completely disabled (red visibility)
+
+/mob/living/silicon/robot/syndicate/can_use_topic(var/src_object)
+ . = ..()
+ if(. != STATUS_INTERACTIVE)
+ return
+
+ if(z in config.admin_levels) // Syndicate borgs can interact with everything on the admin level
+ return STATUS_INTERACTIVE
+ if(istype(get_area(src), /area/syndicate_station)) // If elsewhere, they can interact with everything on the syndicate shuttle
+ return STATUS_INTERACTIVE
+ if(istype(src_object, /obj/machinery)) // Otherwise they can only interact with emagged machinery
+ var/obj/machinery/Machine = src_object
+ if(Machine.emagged)
+ return STATUS_INTERACTIVE
+ return STATUS_UPDATE
+
+/mob/living/silicon/ai/can_use_topic(var/src_object)
+ if(!client || check_unable(1))
+ return STATUS_CLOSE
+ // 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 config.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
+ //apc_override is needed here because AIs use their own APC when powerless
+ if(cameranet && !cameranet.checkTurfVis(get_turf(src_object)))
+ return apc_override ? STATUS_INTERACTIVE : STATUS_CLOSE
+ return STATUS_INTERACTIVE
+
+ return STATUS_CLOSE
+
+/mob/living/proc/shared_living_nano_interaction(var/src_object)
+ if (src.stat != CONSCIOUS)
+ return STATUS_CLOSE // no updates, close the interface
+ else if (restrained() || lying || stat || stunned || weakened)
+ return STATUS_UPDATE // update only (orange visibility)
+ return STATUS_INTERACTIVE
+
+/mob/living/proc/shared_living_nano_distance(var/atom/movable/src_object)
+ if(!isturf(src_object.loc))
+ if(src_object.loc == src) // Item in the inventory
+ return STATUS_INTERACTIVE
+ if(src.contents.Find(src_object.loc)) // A hidden uplink inside an item
+ return STATUS_INTERACTIVE
+
+ 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/can_use_topic(var/src_object, var/datum/topic_state/custom_state)
+ . = shared_living_nano_interaction(src_object)
+ if(. == STATUS_INTERACTIVE && !(custom_state.flags & NANO_IGNORE_DISTANCE))
+ . = shared_living_nano_distance(src_object)
+ if(STATUS_INTERACTIVE)
+ return STATUS_UPDATE
+
+/mob/living/carbon/human/can_use_topic(var/src_object, var/datum/topic_state/custom_state)
+ . = shared_living_nano_interaction(src_object)
+ if(. == STATUS_INTERACTIVE && !(custom_state.flags & NANO_IGNORE_DISTANCE))
+ . = 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
+
+/var/global/datum/topic_state/default_state = new()
+
+/datum/topic_state
+ var/flags = 0
+
+/datum/topic_state/proc/href_list(var/mob/user)
+ return list()
\ No newline at end of file
diff --git a/code/modules/nano/nanomanager.dm b/code/modules/nano/nanomanager.dm
index 36241b2ec75..1fd76dcf726 100644
--- a/code/modules/nano/nanomanager.dm
+++ b/code/modules/nano/nanomanager.dm
@@ -186,7 +186,8 @@
return 0 // wasn't open
processing_uis.Remove(ui)
- ui.user.open_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)
diff --git a/code/modules/nano/nanoprocs.dm b/code/modules/nano/nanoprocs.dm
deleted file mode 100644
index 81b939cf5c4..00000000000
--- a/code/modules/nano/nanoprocs.dm
+++ /dev/null
@@ -1,11 +0,0 @@
-/atom/movable/proc/nano_host()
- return src
-
-/obj/nano_module/nano_host()
- return loc
-
-/atom/movable/proc/nano_can_update()
- return 1
-
-/obj/machinery/nano_can_update()
- return !(stat & (NOPOWER|BROKEN))
diff --git a/code/modules/nano/nanoui.dm b/code/modules/nano/nanoui.dm
index 884fee74982..0a588e9b51a 100644
--- a/code/modules/nano/nanoui.dm
+++ b/code/modules/nano/nanoui.dm
@@ -13,8 +13,6 @@ nanoui is used to open and update nano browser uis
var/atom/movable/src_object
// the title of this ui
var/title
- // /vg/ - Whether to write debug information to nano/debug.html
- var/writeDebug=TRUE
// 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
@@ -53,13 +51,14 @@ nanoui is used to open and update nano browser uis
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/custom_state = null
+
var/cached_data = null
-
- // Only allow users with a certain user.stat to get updates. Defaults to 0 (concious)
- var/allowed_user_stat = 0 // -1 = ignore, 0 = alive, 1 = unconcious or alive, 2 = dead concious or alive
-
/**
* Create a new nanoui instance.
*
@@ -74,17 +73,22 @@ nanoui is used to open and update nano browser uis
*
* @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)
+/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/custom_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.custom_state = custom_state
+
// add the passed template filename as the "main" template, this is required
add_template("main", ntemplate_filename)
if (ntitle)
- title = ntitle
+ title = sanitize(ntitle)
if (nwidth)
width = nwidth
if (nheight)
@@ -139,120 +143,13 @@ nanoui is used to open and update nano browser uis
*/
/datum/nanoui/proc/update_status(var/push_update = 0)
var/atom/movable/host = src_object.nano_host()
- if(!host.nano_can_update())
+ var/new_status = host.CanUseTopic(user, list(), custom_state)
+ if(master_ui)
+ new_status = min(new_status, master_ui.status)
+
+ set_status(new_status, push_update)
+ if(new_status == STATUS_CLOSE)
close()
- return
-
- var/status = user.can_interact_with_interface(host.nano_host())
- set_status(status, push_update)
- if(status == STATUS_CLOSE)
- close()
-
-/*
- Procs called by update_status()
-*/
-
-/mob/living/silicon/pai/can_interact_with_interface(src_object)
- if(src_object == src && !stat)
- return STATUS_INTERACTIVE
- else
- return ..()
-
-/mob/proc/can_interact_with_interface(var/src_object)
- return STATUS_CLOSE // By default no mob can do anything with NanoUI
-
-/mob/dead/observer/can_interact_with_interface()
- if(check_rights(R_ADMIN, 0))
- return STATUS_INTERACTIVE // Admins are more equal
- return STATUS_UPDATE // Ghosts can view updates
-
-/mob/living/silicon/robot/can_interact_with_interface(var/src_object)
- if(stat || !client)
- return STATUS_CLOSE
- if(lockcharge || stunned || weakened)
- return STATUS_DISABLED
- if (src_object in view(client.view, src)) // robots can see and interact with things they can see within their view range
- return STATUS_INTERACTIVE // interactive (green visibility)
- return STATUS_DISABLED // no updates, completely disabled (red visibility)
-
-/mob/living/silicon/robot/syndicate/can_interact_with_interface(var/src_object)
- . = ..()
- if(. != STATUS_INTERACTIVE)
- return
-
- if(z in config.admin_levels) // Syndicate borgs can interact with everything on the admin level
- return STATUS_INTERACTIVE
- if(istype(get_area(src), /area/syndicate_station) || istype(get_area(src), /area/traitor)) // If elsewhere, they can interact with everything on the syndicate shuttle and traitor station
- return STATUS_INTERACTIVE
- if(istype(src_object, /obj/machinery)) // And they can also interact with everything else
- /*var/obj/machinery/Machine = src_object
- if(Machine.emagged) // Uncomment so they can only interact with emagged machinery
- return STATUS_INTERACTIVE*/
- return STATUS_INTERACTIVE
- return STATUS_UPDATE
-
-/mob/living/silicon/ai/can_interact_with_interface(var/src_object)
- if(!client || check_unable(1))
- return STATUS_CLOSE
- // 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 config.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
- //apc_override is needed here because AIs use their own APC when powerless
- if(cameranet && !cameranet.checkTurfVis(get_turf(src_object)))
- return apc_override ? STATUS_INTERACTIVE : STATUS_CLOSE
- return STATUS_INTERACTIVE
-
- return STATUS_CLOSE
-
-/mob/living/proc/shared_living_nano_interaction(var/src_object)
- if (src.stat != CONSCIOUS)
- return STATUS_CLOSE // no updates, close the interface
- else if (restrained() || lying || stat || stunned || weakened)
- return STATUS_UPDATE // update only (orange visibility)
- return STATUS_INTERACTIVE
-
-/mob/living/proc/shared_living_nano_distance(var/atom/movable/src_object)
- if(!isturf(src_object.loc))
- if(src_object.loc == src) // Item in the inventory
- return STATUS_INTERACTIVE
- if(src.contents.Find(src_object.loc)) // A hidden uplink inside an item
- return STATUS_INTERACTIVE
-
- 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/can_interact_with_interface(var/src_object, var/be_close = 1)
- . = shared_living_nano_interaction(src_object)
- if(. == STATUS_INTERACTIVE && be_close)
- . = shared_living_nano_distance(src_object)
- if(STATUS_INTERACTIVE)
- return STATUS_UPDATE
-
-/mob/living/carbon/human/can_interact_with_interface(var/src_object, var/be_close = 1)
- . = shared_living_nano_interaction(src_object)
- if(. == STATUS_INTERACTIVE && be_close)
- . = 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
/**
* Set the ui to auto update (every master_controller tick)
@@ -408,7 +305,7 @@ nanoui is used to open and update nano browser uis
*/
/datum/nanoui/proc/set_show_map(nstate)
show_map = nstate
-
+
/**
* Toggle showing the map ui
*
@@ -495,20 +392,15 @@ nanoui is used to open and update nano browser uis
* @return nothing
*/
/datum/nanoui/proc/open()
-
var/window_size = ""
if (width && height)
window_size = "size=[width]x[height];"
update_status(0)
if(status == STATUS_CLOSE)
return
- var/html=get_html()
- if(src.writeDebug)
- var/f = file("nano/debug.html")
- fdel(f)
- f << html
- user << browse(html, "window=[window_id];[window_size][window_options]")
- winset(user, "mapwindow.map", "focus=true") // Return keyboard focus to map.
+
+ 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)
nanomanager.ui_opened(src)
@@ -522,6 +414,8 @@ nanoui is used to open and update nano browser uis
is_auto_updating = 0
nanomanager.ui_closed(src)
user << browse(null, "window=[window_id]")
+ for(var/datum/nanoui/child in children)
+ child.close()
/**
* Set the UI window to call the nanoclose verb when the window is closed
@@ -535,11 +429,12 @@ nanoui is used to open and update nano browser uis
var/params = "\ref[src]"
winset(user, window_id, "on-close=\"nanoclose [params]\"")
-
+
/**
* Appends already processed json txt to the list2json proc when setting initial-data and data pushes
* Used for data that is fucking huge like manifests and camera lists that doesn't change often.
* And we only want to process them when they change.
+ * Fuck javascript
*
* @return nothing
*/
@@ -547,6 +442,7 @@ nanoui is used to open and update nano browser uis
cached_data = data
return
+
/**
* Push data to an already open UI window
*
@@ -579,12 +475,12 @@ nanoui is used to open and update nano browser uis
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)) || map_update)
+ if ((src_object && src_object.Topic(href, href_list, 0, custom_state)) || map_update)
nanomanager.update_uis(src_object) // update all UIs attached to src_object
/**
@@ -611,5 +507,4 @@ nanoui is used to open and update nano browser uis
* @return nothing
*/
/datum/nanoui/proc/update(var/force_open = 0)
- src_object.ui_interact(user, ui_key, src, force_open)
-
+ src_object.ui_interact(user, ui_key, src, force_open, master_ui, custom_state)
diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm
index 86dfcc247c4..d0cf07fc9e1 100644
--- a/code/modules/power/apc.dm
+++ b/code/modules/power/apc.dm
@@ -691,8 +691,12 @@
else
beenhit += 1
return
-
-
+
+/obj/machinery/power/apc/attack_ghost(user as mob)
+ if(stat & (BROKEN|MAINT))
+ return
+ return ui_interact(user)
+
/obj/machinery/power/apc/interact(mob/user)
if(!user)
return
diff --git a/code/modules/power/smes.dm b/code/modules/power/smes.dm
index 1f1e01938fb..d7fedfb7a8f 100644
--- a/code/modules/power/smes.dm
+++ b/code/modules/power/smes.dm
@@ -332,6 +332,9 @@
add_fingerprint(user)
ui_interact(user)
+/obj/machinery/power/smes/attack_ghost(mob/user)
+ ui_interact(user)
+
/obj/machinery/power/smes/attack_hand(mob/user)
add_fingerprint(user)
ui_interact(user)
diff --git a/code/setup.dm b/code/setup.dm
index db4fe56cb65..c18d1ac0d12 100644
--- a/code/setup.dm
+++ b/code/setup.dm
@@ -968,6 +968,8 @@ var/list/hit_appends = list("-OOF", "-ACK", "-UGH", "-HRNK", "-HURGH", "-GLORF")
#define STATUS_DISABLED 0 // RED Visability
#define STATUS_CLOSE -1 // Close the interface
+#define NANO_IGNORE_DISTANCE 1
+
//Click cooldowns, in tenths of a second
#define CLICK_CD_MELEE 8
#define CLICK_CD_RANGE 4
diff --git a/nano/css/shared.css b/nano/css/shared.css
index a733031b8de..02476dcb8f1 100644
--- a/nano/css/shared.css
+++ b/nano/css/shared.css
@@ -128,7 +128,7 @@ img, a img {
h1, h2, h3, h4, h5, h6 {
margin: 0;
padding: 12px 0 6px 0;
- color: #517087;
+ color: #FFFFFF;
clear: both;
}
@@ -488,6 +488,14 @@ div.notice {
text-align: center;
}
+table.fixed {
+ table-layout:fixed;
+}
+
+table.fixed td {
+ overflow: hidden;
+}
+
/* Table styling for the power monitor */
table.pmon {
border: 2px solid RoyalBlue;
diff --git a/nano/js/nano_base_helpers.js b/nano/js/nano_base_helpers.js
index 67dffc064cc..40c6b6077e5 100644
--- a/nano/js/nano_base_helpers.js
+++ b/nano/js/nano_base_helpers.js
@@ -64,6 +64,9 @@ NanoBaseHelpers = function ()
round: function(number) {
return Math.round(number);
},
+ fixed: function(number) {
+ return Math.round(number * 10) / 10;
+ },
// Round a number down to integer
floor: function(number) {
return Math.floor(number);
diff --git a/paradise.dme b/paradise.dme
index fff8f6e2281..c45f9ec2a06 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -1418,9 +1418,9 @@
#include "code\modules\nano\JSON Reader.dm"
#include "code\modules\nano\JSON Writer.dm"
#include "code\modules\nano\nanoexternal.dm"
+#include "code\modules\nano\nanointeraction.dm"
#include "code\modules\nano\nanomanager.dm"
#include "code\modules\nano\nanomapgen.dm"
-#include "code\modules\nano\nanoprocs.dm"
#include "code\modules\nano\nanoui.dm"
#include "code\modules\nano\modules\crew_monitor.dm"
#include "code\modules\organs\blood.dm"