");
+
+ if (area && pos_x && pos_y) { tdElem.append($("").text(area).addClass("tt").append($("").append($("").text("(" + pos_x + ", " + pos_y + ")")))); }
+ else { tdElem.text("Not Available"); }
+
+ trElem.append(tdElem);
+
+ $("#textbased-tbody").append(trElem);
+
+ if (updateMap && pos_x && pos_y && (in_range == "1"))
+ {
+ var x = parseInt(pos_x);
+ var y = maxy - parseInt(pos_y);
+
+ var tx = (translate(x - 1, scale_x) - 1.5).toFixed(0);
+ var ty = (translate(y - 1, scale_y) + 3).toFixed(0);
+
+ var dotElem = $("");
+
+ $("#minimap").append(dotElem);
+
+ function enable()
+ {
+ dotElem.css({ "border-color": color, "z-index": 9999, "width": "8px", "height": "8px", "margin-top": "-2px", "margin-left": "-3px" });
+ }
+
+ function disable()
+ {
+ dotElem.css({ "border-color": "transparent", "z-index": ijob, "width": "3px", "height": "3px", "margin-top": "0px", "margin-left": "0px", "filter": "" });
+ }
+
+ function click(e)
+ {
+ e.preventDefault();
+ e.stopPropagation();
+
+ window.location.href = "byond://?src=" + hSrc + "&action=select_person&name=" + encodeURIComponent(name);
+ }
+
+ trElem.on("mouseover", enable).on("mouseout", disable).on("click", click);
+
+ dotElem.on("mouseover", function()
+ {
+ trElem.addClass("hover");
+ enable();
+ }).on("mouseout", function()
+ {
+ trElem.removeClass("hover");
+ disable();
+ }).on("click", click);
+ }
+}
+
+function translate(n, scale)
+{
+ return (n * tile_size) * scale;
+}
\ No newline at end of file
diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm
index fbfc193fb61..02221971859 100644
--- a/code/game/machinery/machinery.dm
+++ b/code/game/machinery/machinery.dm
@@ -418,7 +418,7 @@ Class Procs:
return 0
// Hook for html_interface module to prevent updates to clients who don't have this as their active machine.
-/obj/machinery/proc/hiIsValidClient(datum/html_interface_client/hclient)
+/obj/machinery/proc/hiIsValidClient(datum/html_interface_client/hclient, datum/html_interface/hi)
if (hclient.client.mob && hclient.client.mob.stat == 0)
if (isAI(hclient.client.mob)) return TRUE
else return hclient.client.mob.machine == src && src.Adjacent(hclient.client.mob)
@@ -427,4 +427,4 @@ Class Procs:
// Hook for html_interface module to unset the active machine when the window is closed by the player.
/obj/machinery/proc/hiOnHide(datum/html_interface_client/hclient)
- if (hclient.client.mob && hclient.client.mob.machine == src) hclient.client.mob.unset_machine()
+ if (hclient.client.mob && hclient.client.mob.machine == src) hclient.client.mob.unset_machine()
diff --git a/code/game/objects/items/devices/sensor_device.dm b/code/game/objects/items/devices/sensor_device.dm
index 2bcddf5de79..9d4bbc60b43 100644
--- a/code/game/objects/items/devices/sensor_device.dm
+++ b/code/game/objects/items/devices/sensor_device.dm
@@ -8,4 +8,4 @@
origin_tech = "programming=3;materials=3;magnets=3"
/obj/item/device/sensor_device/attack_self(mob/user as mob)
- crewmonitor(user,src) //Proc already exists, just had to call it
+ crewmonitor.show(user) //Proc already exists, just had to call it
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index 0ce5eef9209..23e0bc6142e 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -125,7 +125,8 @@ var/list/admin_verbs_debug = list(
/client/proc/test_snap_UI,
/client/proc/debugNatureMapGenerator,
/client/proc/check_bomb_impacts,
- /proc/machine_upgrade
+ /proc/machine_upgrade,
+ /client/proc/populate_world
)
var/list/admin_verbs_possess = list(
/proc/possess,
@@ -260,7 +261,7 @@ var/list/admin_verbs_hideable = list(
/client/proc/fps,
/client/proc/cmd_admin_grantfullaccess,
/client/proc/cmd_admin_areatest,
- /client/proc/readmin
+ /client/proc/readmin,
)
if(holder)
verbs.Remove(holder.rank.adds)
@@ -595,3 +596,38 @@ var/list/admin_verbs_hideable = list(
verbs -= /client/proc/readmin
deadmins -= ckey
return
+
+/client/proc/populate_world(var/amount = 50 as num)
+ set name = "Populate World"
+ set category = "Debug"
+ set desc = "(\"Amount of mobs to create\") Populate the world with test mobs."
+
+ if (amount > 0)
+ var/area/area
+ var/list/candidates
+ var/turf/simulated/floor/tile
+ var/j,k
+ var/mob/living/carbon/human/mob
+
+ for (var/i = 1 to amount)
+ j = 100
+
+ do
+ area = pick(the_station_areas)
+
+ if (area)
+
+ candidates = get_area_turfs(area)
+
+ if (candidates.len)
+ k = 100
+
+ do
+ tile = pick(candidates)
+ while ((!tile || !istype(tile)) && --k > 0)
+
+ if (tile)
+ mob = new/mob/living/carbon/human/interactive(tile)
+
+ testing("Spawned test mob with name \"[mob.name]\" at [tile.x],[tile.y],[tile.z]")
+ while (!area && --j > 0)
\ No newline at end of file
diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm
index f1024432765..366f113a114 100644
--- a/code/modules/client/client procs.dm
+++ b/code/modules/client/client procs.dm
@@ -280,6 +280,11 @@ var/next_external_rsc = 0
hi = new type(null)
hi.sendResources(src)
+ // Preload the crew monitor. This needs to be done due to BYOND bug http://www.byond.com/forum/?post=1487244
+ spawn
+ if (crewmonitor && crewmonitor.initialized)
+ crewmonitor.sendResources(src)
+
//Send nanoui files to client
SSnano.send_resources(src)
getFiles(
diff --git a/code/modules/games/cards.dm b/code/modules/games/cards.dm
index a39c6f54dc0..379adeecace 100644
--- a/code/modules/games/cards.dm
+++ b/code/modules/games/cards.dm
@@ -248,5 +248,5 @@
src.toggle_conceal()
// Hook for html_interface module to prevent updates to clients who don't have this in their inventory.
-/obj/item/weapon/hand/proc/hiIsValidClient(datum/html_interface_client/hclient)
+/obj/item/weapon/hand/proc/hiIsValidClient(datum/html_interface_client/hclient, datum/html_interface/hi)
return (hclient.client.mob && hclient.client.mob.stat == 0 && (src in hclient.client.mob.contents))
diff --git a/code/modules/html_interface/html_interface.dm b/code/modules/html_interface/html_interface.dm
index 0c9984f0b06..2e3359e80c4 100644
--- a/code/modules/html_interface/html_interface.dm
+++ b/code/modules/html_interface/html_interface.dm
@@ -54,6 +54,10 @@ Hides the HTML interface from the provided client. This will close the browser w
Returns TRUE if the interface is being used (has an active client) or FALSE if not.
+ hi.closeAll()
+
+Closes the interface on all clients.
+
** Additional notes **
When working with byond:// links make sure to reference the HTML interface object and NOT the original object. Topic() will still be called on
@@ -74,6 +78,8 @@ mob/verb/test()
*/
+/var/list/html_interfaces = new/list()
+
/datum/html_interface
// The atom we should report to.
var/atom/ref
@@ -100,6 +106,8 @@ mob/verb/test()
var/height
/datum/html_interface/New(atom/ref, title, width = 700, height = 480, head = "")
+ html_interfaces.Add(src)
+
. = ..()
src.ref = ref
@@ -109,9 +117,9 @@ mob/verb/test()
src.head = head
/datum/html_interface/Destroy()
- if (src.clients)
- for (var/client in src.clients)
- src.hide(src.clients[client])
+ src.closeAll()
+
+ html_interfaces.Remove(src)
return ..()
@@ -160,7 +168,19 @@ mob/verb/test()
if (istype(hclient))
if (hclient.is_loaded) hclient.client << output(list2params(list(jscript)), "browser_\ref[src].browser:eval")
else
- for (var/client in src.clients) src.executeJavaScript(jscript, src.clients[client])
+ for (var/client in src.clients) if(src.clients[client]) src.executeJavaScript(jscript, src.clients[client])
+
+/datum/html_interface/proc/callJavaScript(func, list/arguments, datum/html_interface_client/hclient = null)
+ if (!arguments) arguments = new/list()
+
+ if (hclient)
+ hclient = getClient(hclient)
+
+ if (istype(hclient))
+ if (hclient.is_loaded)
+ hclient.client << output(list2params(arguments), "browser_\ref[src].browser:[func]")
+ else
+ for (var/client in src.clients) if (src.clients[client]) src.callJavaScript(func, arguments, src.clients[client])
/datum/html_interface/proc/updateLayout(layout)
src.layout = layout
@@ -180,7 +200,8 @@ mob/verb/test()
for (var/client in src.clients)
hclient = src._getClient(src.clients[client])
- if (hclient && hclient.active) src._renderContent(id, hclient, ignore_cache)
+ if (hclient && hclient.active)
+ spawn (-1) src._renderContent(id, hclient, ignore_cache)
/datum/html_interface/proc/show(datum/html_interface_client/hclient)
hclient = getClient(hclient, TRUE)
@@ -200,6 +221,8 @@ mob/verb/test()
hclient.client << output(replacetextEx(replacetextEx(file2text('html_interface.html'), "\[hsrc\]", "\ref[src]"), "", "[head]"), "browser_\ref[src].browser")
winshow(hclient.client, "browser_\ref[src]", TRUE)
+ while (hclient.client && hclient.active && !hclient.is_loaded) sleep(2)
+
/datum/html_interface/proc/hide(datum/html_interface_client/hclient)
hclient = getClient(hclient)
@@ -243,24 +266,34 @@ mob/verb/test()
/datum/html_interface/proc/isUsed()
if (src.clients && src.clients.len > 0)
var/datum/html_interface_client/hclient
+
for (var/key in clients)
- hclient = clients[key]
- if (hclient.active) return TRUE
+ hclient = _getClient(clients[key])
+
+ if (hclient)
+ if (hclient.active) return TRUE
+ else
+ clients.Remove(key)
return FALSE
+/datum/html_interface/proc/closeAll()
+ if (src.clients)
+ for (var/client in src.clients)
+ src.hide(src.clients[client])
+
/* * Danger Zone */
/datum/html_interface/proc/_getClient(datum/html_interface_client/hclient)
if (hclient)
if (hclient.client)
- if (hascall(src.ref, "hiIsValidClient"))
- var/res = call(src.ref, "hiIsValidClient")(hclient)
+ // res = if the client has been active in the past 10 minutes and the client is allowed to view the object (context-sensitive).
+ var/res = hclient.client.inactivity <= 6000 && (hascall(src.ref, "hiIsValidClient") ? call(src.ref, "hiIsValidClient")(hclient, src) : TRUE)
- if (res)
- if (!hclient.active) src.enableFor(hclient)
- else
- if (hclient.active) src.disableFor(hclient)
+ if (res)
+ if (!hclient.active) src.enableFor(hclient)
+ else
+ if (hclient.active) src.disableFor(hclient)
return hclient
else
@@ -268,8 +301,8 @@ mob/verb/test()
else
return null
-/datum/html_interface/proc/_renderTitle(datum/html_interface_client/hclient, ignore_cache = FALSE)
- if (hclient && hclient.is_loaded)
+/datum/html_interface/proc/_renderTitle(datum/html_interface_client/hclient, ignore_cache = FALSE, ignore_loaded = FALSE)
+ if (hclient && (ignore_loaded || hclient.is_loaded))
// Only render if we have new content.
if (ignore_cache || src.title != hclient.title)
@@ -279,8 +312,8 @@ mob/verb/test()
hclient.client << output(list2params(list(title)), "browser_\ref[src].browser:setTitle")
-/datum/html_interface/proc/_renderLayout(datum/html_interface_client/hclient)
- if (hclient && hclient.is_loaded)
+/datum/html_interface/proc/_renderLayout(datum/html_interface_client/hclient, ignore_loaded = FALSE)
+ if (hclient && (ignore_loaded || hclient.is_loaded))
var/html = src.layout
// Only render if we have new content.
@@ -289,10 +322,10 @@ mob/verb/test()
hclient.client << output(list2params(list(html)), "browser_\ref[src].browser:updateLayout")
- for (var/id in src.content_elements) src._renderContent(id, hclient)
+ for (var/id in src.content_elements) src._renderContent(id, hclient, ignore_loaded = ignore_loaded)
-/datum/html_interface/proc/_renderContent(id, datum/html_interface_client/hclient, ignore_cache = FALSE)
- if (hclient && hclient.is_loaded)
+/datum/html_interface/proc/_renderContent(id, datum/html_interface_client/hclient, ignore_cache = FALSE, ignore_loaded = FALSE)
+ if (hclient && (ignore_loaded || hclient.is_loaded))
var/html = src.content_elements[id]
// Only render if we have new content.
@@ -311,10 +344,11 @@ mob/verb/test()
if ("onload")
hclient.layout = null
hclient.content_elements.len = 0
- hclient.is_loaded = TRUE
- src._renderTitle(hclient, TRUE)
- src._renderLayout(hclient)
+ src._renderTitle(hclient, TRUE, TRUE)
+ src._renderLayout(hclient, TRUE)
+
+ hclient.is_loaded = TRUE
if ("onclose")
src.hide(hclient)
diff --git a/code/modules/html_interface/nanotrasen/nanotrasen.css b/code/modules/html_interface/nanotrasen/nanotrasen.css
index 2b5a2cc418c..702a381c077 100644
--- a/code/modules/html_interface/nanotrasen/nanotrasen.css
+++ b/code/modules/html_interface/nanotrasen/nanotrasen.css
@@ -11,6 +11,12 @@ body
line-height: 170%; /* NullQuery: 170% of what? */
}
+/* Fix for IE8 */
+body
+{
+ background-color: #1F1F1F\9 !important;
+}
+
#ntbgcenter
{
position: absolute;
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 3ab80a622bb..000893f5165 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -849,7 +849,7 @@ Sorry Giacom. Please don't be mad :(
return 0
if(T.z >= ZLEVEL_SPACEMAX)
return 0
- if(src == user)
+ if(user != null && src == user)
return 0
if(invisibility || alpha == 0)//cloaked
return 0
diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm
index a0106cfcc02..f80afc9d4f8 100644
--- a/code/modules/mob/mob_movement.dm
+++ b/code/modules/mob/mob_movement.dm
@@ -389,4 +389,4 @@
return
/mob/proc/update_gravity()
- return
+ return
\ No newline at end of file
diff --git a/html/changelogs/NullQuery-Nullstation-hi-extended.yml b/html/changelogs/NullQuery-Nullstation-hi-extended.yml
new file mode 100644
index 00000000000..de45b1a1e55
--- /dev/null
+++ b/html/changelogs/NullQuery-Nullstation-hi-extended.yml
@@ -0,0 +1,11 @@
+author: NullQuery
+delete-after: True
+
+changes:
+ - tweak: "The crew monitoring computer, AI crew monitoring popup and the handheld crew monitor now update automatically."
+ - tweak: "Crew monitoring: The health information has been turned into a health indicator. It goes from green to red. Hovering over the icon shows detailed information (if available)."
+ - tweak: "Crew monitoring: The location coordinates have been hidden. You can see them by hovering over the 'Location' column."
+ - rscadd: "Crew monitoring: A minimap has been added so you can easily see where people are."
+ - tweak: "Crew monitoring: Players who are not in range of a camera are not shown on the minimap."
+ - tweak: "Crew monitoring: AI players can quickly move to other locations or track players by clicking the minimap or items in the table."
+ - tweak: "Crew monitoring: For AI players, health information always shows a white indicator instead of green-to-red. This is a deliberate limitation to prevent the AI from becoming too omnipresent."
diff --git a/html/mapbase1024.png b/html/mapbase1024.png
new file mode 100644
index 00000000000..a927a71b6e7
Binary files /dev/null and b/html/mapbase1024.png differ
diff --git a/interface/interface.dm b/interface/interface.dm
index ffaeadc5776..a24e86cd3aa 100644
--- a/interface/interface.dm
+++ b/interface/interface.dm
@@ -171,4 +171,11 @@ Any-Mode: (hotkey doesn't need to be on)
"}
src << hotkey_mode
- src << other
\ No newline at end of file
+ src << other
+
+// Needed to circumvent a bug where .winset does not work when used on the window.on-size event in skins.
+// Used by /datum/html_interface/nanotrasen (code/modules/html_interface/nanotrasen/nanotrasen.dm)
+/client/verb/_swinset(var/x as text)
+ set name = ".swinset"
+ set hidden = 1
+ winset(src, null, x)
diff --git a/tgstation.dme b/tgstation.dme
index f12e17995b7..3789e9e11fd 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -136,6 +136,7 @@
#include "code\controllers\subsystem\npcpool.dm"
#include "code\controllers\subsystem\objects.dm"
#include "code\controllers\subsystem\pai.dm"
+#include "code\controllers\subsystem\procqueue.dm"
#include "code\controllers\subsystem\radio.dm"
#include "code\controllers\subsystem\server_maintenance.dm"
#include "code\controllers\subsystem\shuttles.dm"