Crew monitoring computer v1.1

It just werks edition
There is a check now for html range that doesn't require calling range() and allows silicons to use it at range
The dot on the minimap is still super fucking small, I need to find the element to make it larger
This commit is contained in:
clusterfack
2015-07-07 20:43:13 -05:00
parent 9417d5149b
commit 4340f5b61e
10 changed files with 279 additions and 326 deletions

View File

@@ -102,4 +102,24 @@ a { display: none; }
{
position: relative;
top: -2px;
}
}
.dot
{
transition: .2s all;
position: absolute;
width: 3px;
height: 3px;
margin-top: 0px;
margin-left: 0px;
border: 1px solid transparent;
}
.dot.active
{
z-index: 9999 !important;
width: 8px;
height: 8px;
margin-top: -2px;
margin-left: -3px;
}

View File

@@ -14,8 +14,13 @@
/obj/machinery/computer/crew/New()
tracked = list()
html_machines += src
..()
/obj/machinery/computer/crew/Destroy()
..()
html_machines -= src
/obj/machinery/computer/crew/attack_ai(mob/user)
attack_hand(user)
@@ -84,9 +89,6 @@ var/global/datum/crewmonitor/crewmonitor = new
jobs["Lawyer"] = 69
jobs["Admiral"] = 200
jobs["Centcom Commander"] = 210
jobs["Custodian"] = 211
jobs["Medical Officer"] = 212
jobs["Research Officer"] = 213
jobs["Emergency Response Team Commander"] = 220
jobs["Security Response Officer"] = 221
jobs["Engineer Response Officer"] = 222
@@ -100,10 +102,11 @@ var/global/datum/crewmonitor/crewmonitor = new
/datum/crewmonitor/Destroy()
if (src.interfaces)
for (var/datum/html_interface/hi in interfaces)
qdel(hi)
Destroy(hi)
src.interfaces = null
return ..()
/datum/crewmonitor/proc/show(mob/mob, z)
if (!z) z = mob.z
@@ -206,13 +209,12 @@ var/global/datum/crewmonitor/crewmonitor = new
pos_x = null
pos_y = null
results[++results.len] = list(name, assignment, ijob, life_status, dam1, dam2, dam3, dam4, area, pos_x, pos_y, H.can_track())
results[++results.len] = list(name, assignment, ijob, life_status, dam1, dam2, dam3, dam4, area, pos_x, pos_y, H.monitor_check())
src.data = results
src.updateFor(null, hi, z) // updates for everyone
/mob/living/carbon/human/proc/can_track()
//basic fast checks go first. When overriding this proc, I recommend calling ..() at the end.
/mob/living/carbon/human/proc/monitor_check()
var/turf/T = get_turf(src)
if(!T)
return 0
@@ -228,7 +230,7 @@ var/global/datum/crewmonitor/crewmonitor = new
for (z in src.interfaces)
if (src.interfaces[z] == hi) break
return (hclient.client.mob && hclient.client.mob.stat == 0 && hclient.client.mob.z == text2num(z) && ( isAI(hclient.client.mob) || (locate(/obj/machinery/computer/crew, range(1, hclient.client.mob))) ) )
return (hclient.client.mob && hclient.client.mob.stat == 0 && hclient.client.mob.z == text2num(z) && hclient.client.mob.html_mob_check(/obj/machinery/computer/crew))
/datum/crewmonitor/Topic(href, href_list[], datum/html_interface_client/hclient)
if (istype(hclient))
@@ -441,127 +443,3 @@ var/global/datum/crewmonitor/crewmonitor = new
#ifdef MINIMAP_DEBUG
#undef MINIMAP_DEBUG
#endif
/*
/obj/machinery/computer/crew/interact(mob/user)
ui_interact(user)
/obj/machinery/computer/crew/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
if(stat & (BROKEN|NOPOWER))
return
user.set_machine(src)
src.scan()
var/data[0]
var/list/crewmembers = list()
for(var/mob/living/carbon/brain/B in mob_list)
var/turf/pos = get_turf(B)
if(!pos) continue
var/obj/item/device/mmi/M = B.loc
if(istype(M) && M.brainmob == B)
if(isrobot(M.loc))
continue
var/list/crewmemberData = list()
crewmemberData["sensor_type"] = 3
crewmemberData["dead"] = 0
crewmemberData["oxy"] = 0
crewmemberData["tox"] = 0
crewmemberData["fire"] = 0
crewmemberData["brute"] = 0
crewmemberData["name"] = M.name
crewmemberData["rank"] = "Unknown"
crewmemberData["area"] = get_area(M)
crewmemberData["x"] = pos.x
crewmemberData["y"] = pos.y
crewmemberData["z"] = pos.z
crewmemberData["xoffset"] = pos.x-WORLD_X_OFFSET[pos.z]
crewmemberData["yoffset"] = pos.y-WORLD_Y_OFFSET[pos.z]
crewmembers += list(crewmemberData)
for(var/obj/item/clothing/under/C in src.tracked)
var/turf/pos = get_turf(C)
if((C) && (C.has_sensor) && (pos) && (pos.z != CENTCOMM_Z) && C.sensor_mode)
if(istype(C.loc, /mob/living/carbon/human))
var/mob/living/carbon/human/H = C.loc
var/list/crewmemberData = list()
crewmemberData["sensor_type"] = C.sensor_mode
crewmemberData["dead"] = H.stat > 1
crewmemberData["oxy"] = round(H.getOxyLoss(), 1)
crewmemberData["tox"] = round(H.getToxLoss(), 1)
crewmemberData["fire"] = round(H.getFireLoss(), 1)
crewmemberData["brute"] = round(H.getBruteLoss(), 1)
crewmemberData["name"] = "Unknown"
crewmemberData["rank"] = "Unknown"
if(H.wear_id && istype(H.wear_id, /obj/item/weapon/card/id) )
var/obj/item/weapon/card/id/I = H.wear_id
crewmemberData["name"] = I.name
crewmemberData["rank"] = I.rank
else if(H.wear_id && istype(H.wear_id, /obj/item/device/pda) )
var/obj/item/device/pda/P = H.wear_id
crewmemberData["name"] = (P.id ? P.id.name : "Unknown")
crewmemberData["rank"] = (P.id ? P.id.rank : "Unknown")
crewmemberData["area"] = get_area(H)
crewmemberData["x"] = pos.x
crewmemberData["y"] = pos.y
crewmemberData["z"] = pos.z
crewmemberData["xoffset"] = pos.x-WORLD_X_OFFSET[pos.z]
crewmemberData["yoffset"] = pos.y-WORLD_Y_OFFSET[pos.z]
crewmembers += list(crewmemberData)
// Works around list += list2 merging lists; it's not pretty but it works
//crewmembers += "temporary item"
//crewmembers[crewmembers.len] = crewmemberData
crewmembers = sortList(crewmembers)
data["crewmembers"] = crewmembers
//ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui) // no ui has been passed, so we'll search for one
ui = nanomanager.get_open_ui(user, src, ui_key)
if(!ui)
ui = new(user, src, ui_key, "crew_monitor.tmpl", "Crew Monitoring Computer", 900, 800)
// adding a template with the key "mapContent" enables the map ui functionality
ui.add_template("mapContent", "crew_monitor_map_content.tmpl")
// adding a template with the key "mapHeader" replaces the map header content
ui.add_template("mapHeader", "crew_monitor_map_header.tmpl")
// we want to show the map by default
ui.set_show_map(1)
ui.set_initial_data(data)
ui.open()
// should make the UI auto-update; doesn't seem to?
ui.set_auto_update(1)
else
// The UI is already open so push the new data to it
ui.push_data(data)
return
/obj/machinery/computer/crew/proc/is_scannable(const/obj/item/clothing/under/C, const/mob/living/carbon/human/H)
if(!istype(H) || H.iscorpse)
return 0
if(isnull(track_special_role))
return C.has_sensor
return (H.mind ? H.mind.special_role == track_special_role : 1)
/obj/machinery/computer/crew/proc/scan()
for(var/mob/living/carbon/human/H in mob_list)
if(istype(H.w_uniform, /obj/item/clothing/under))
var/obj/item/clothing/under/C = H.w_uniform
if (C.has_sensor)
if(is_scannable(C, H))
tracked |= C
return 1*/

View File

@@ -1,3 +1,212 @@
/*!
* jQuery scrollintoview() plugin and :scrollable selector filter
*
* Version 1.8 (14 Jul 2011)
* Requires jQuery 1.4 or newer
*/
(function ($) {
var converter = {
vertical: { x: false, y: true },
horizontal: { x: true, y: false },
both: { x: true, y: true },
x: { x: true, y: false },
y: { x: false, y: true }
};
var settings = {
duration: "fast",
direction: "both"
};
var rootrx = /^(?:html)$/i;
// gets border dimensions
var borders = function (domElement, styles) {
styles = styles || (document.defaultView && document.defaultView.getComputedStyle ? document.defaultView.getComputedStyle(domElement, null) : domElement.currentStyle);
var px = document.defaultView && document.defaultView.getComputedStyle ? true : false;
var b = {
top: (parseFloat(px ? styles.borderTopWidth : $.css(domElement, "borderTopWidth")) || 0),
left: (parseFloat(px ? styles.borderLeftWidth : $.css(domElement, "borderLeftWidth")) || 0),
bottom: (parseFloat(px ? styles.borderBottomWidth : $.css(domElement, "borderBottomWidth")) || 0),
right: (parseFloat(px ? styles.borderRightWidth : $.css(domElement, "borderRightWidth")) || 0)
};
return {
top: b.top,
left: b.left,
bottom: b.bottom,
right: b.right,
vertical: b.top + b.bottom,
horizontal: b.left + b.right
};
};
var dimensions = function ($element) {
var win = $(window);
var isRoot = rootrx.test($element[0].nodeName);
return {
border: isRoot ? { top: 0, left: 0, bottom: 0, right: 0} : borders($element[0]),
scroll: {
top: (isRoot ? win : $element).scrollTop(),
left: (isRoot ? win : $element).scrollLeft()
},
scrollbar: {
right: isRoot ? 0 : $element.innerWidth() - $element[0].clientWidth,
bottom: isRoot ? 0 : $element.innerHeight() - $element[0].clientHeight
},
rect: (function () {
var r = $element[0].getBoundingClientRect();
return {
top: isRoot ? 0 : r.top,
left: isRoot ? 0 : r.left,
bottom: isRoot ? $element[0].clientHeight : r.bottom,
right: isRoot ? $element[0].clientWidth : r.right
};
})()
};
};
$.fn.extend({
scrollintoview: function (options) {
/// <summary>Scrolls the first element in the set into view by scrolling its closest scrollable parent.</summary>
/// <param name="options" type="Object">Additional options that can configure scrolling:
/// duration (default: "fast") - jQuery animation speed (can be a duration string or number of milliseconds)
/// direction (default: "both") - select possible scrollings ("vertical" or "y", "horizontal" or "x", "both")
/// complete (default: none) - a function to call when scrolling completes (called in context of the DOM element being scrolled)
/// </param>
/// <return type="jQuery">Returns the same jQuery set that this function was run on.</return>
options = $.extend({}, settings, options);
options.direction = converter[typeof (options.direction) === "string" && options.direction.toLowerCase()] || converter.both;
var dirStr = "";
if (options.direction.x === true) dirStr = "horizontal";
if (options.direction.y === true) dirStr = dirStr ? "both" : "vertical";
var el = this.eq(0);
var scroller = el.closest(":scrollable(" + dirStr + ")");
// check if there's anything to scroll in the first place
if (scroller.length > 0)
{
scroller = scroller.eq(0);
var dim = {
e: dimensions(el),
s: dimensions(scroller)
};
var rel = {
top: dim.e.rect.top - (dim.s.rect.top + dim.s.border.top),
bottom: dim.s.rect.bottom - dim.s.border.bottom - dim.s.scrollbar.bottom - dim.e.rect.bottom,
left: dim.e.rect.left - (dim.s.rect.left + dim.s.border.left),
right: dim.s.rect.right - dim.s.border.right - dim.s.scrollbar.right - dim.e.rect.right
};
var animOptions = {};
// vertical scroll
if (options.direction.y === true)
{
if (rel.top < 0)
{
animOptions.scrollTop = dim.s.scroll.top + rel.top;
}
else if (rel.top > 0 && rel.bottom < 0)
{
animOptions.scrollTop = dim.s.scroll.top + Math.min(rel.top, -rel.bottom);
}
}
// horizontal scroll
if (options.direction.x === true)
{
if (rel.left < 0)
{
animOptions.scrollLeft = dim.s.scroll.left + rel.left;
}
else if (rel.left > 0 && rel.right < 0)
{
animOptions.scrollLeft = dim.s.scroll.left + Math.min(rel.left, -rel.right);
}
}
// scroll if needed
if (!$.isEmptyObject(animOptions))
{
if (rootrx.test(scroller[0].nodeName))
{
scroller = $("html,body");
}
scroller
.animate(animOptions, options.duration)
.eq(0) // we want function to be called just once (ref. "html,body")
.queue(function (next) {
$.isFunction(options.complete) && options.complete.call(scroller[0]);
next();
});
}
else
{
// when there's nothing to scroll, just call the "complete" function
$.isFunction(options.complete) && options.complete.call(scroller[0]);
}
}
// return set back
return this;
}
});
var scrollValue = {
auto: true,
scroll: true,
visible: false,
hidden: false
};
$.extend($.expr[":"], {
scrollable: function (element, index, meta, stack) {
var direction = converter[typeof (meta[3]) === "string" && meta[3].toLowerCase()] || converter.both;
var styles = (document.defaultView && document.defaultView.getComputedStyle ? document.defaultView.getComputedStyle(element, null) : element.currentStyle);
var overflow = {
x: scrollValue[styles.overflowX.toLowerCase()] || false,
y: scrollValue[styles.overflowY.toLowerCase()] || false,
isRoot: rootrx.test(element.nodeName)
};
// check if completely unscrollable (exclude HTML element because it's special)
if (!overflow.x && !overflow.y && !overflow.isRoot)
{
return false;
}
var size = {
height: {
scroll: element.scrollHeight,
client: element.clientHeight
},
width: {
scroll: element.scrollWidth,
client: element.clientWidth
},
// check overflow.x/y because iPad (and possibly other tablets) don't dislay scrollbars
scrollableX: function () {
return (overflow.x || overflow.isRoot) && this.width.scroll > this.width.client;
},
scrollableY: function () {
return (overflow.y || overflow.isRoot) && this.height.scroll > this.height.client;
}
};
return direction.y && size.scrollableY() || direction.x && size.scrollableX();
}
});
})(jQuery);
/*!
* Crew manifest script
*/
var isAI = null;
var scale_x;
var scale_y;
@@ -114,16 +323,16 @@ function add(name, assignment, ijob, life_status, dam1, dam2, dam3, dam4, area,
}
spanElem = $("<span></span>").text(name);
if (italics)
{
spanElem.css("font-style", "italic");
}
if (isHead(ijob)) { spanElem.css("font-weight", "bold"); }
var color = getColor(ijob);
if (color) { spanElem.css("color", color); }
tdElem.append(spanElem);
@@ -144,7 +353,10 @@ function add(name, assignment, ijob, life_status, dam1, dam2, dam3, dam4, area,
trElem.append(tdElem);
$("#textbased-tbody").append(trElem);
var item = $("#textbased-tbody > tr").filter(function(){ return parseInt($(this).attr("data-ijob")) >= ijob; }).eq(0);
if (item.length > 0) { trElem.insertBefore(item); }
else { $("#textbased-tbody").append(trElem); }
if (updateMap && pos_x && pos_y && (in_range == "1"))
{
@@ -154,18 +366,18 @@ function add(name, assignment, ijob, life_status, dam1, dam2, dam3, dam4, area,
var tx = (translate(x - 1, scale_x) - 1.5).toFixed(0);
var ty = (translate(y - 1, scale_y) + 3).toFixed(0);
var dotElem = $("<div class=\"dot\" style=\"transition: .2s all; position: absolute; top: " + ty + "px; left: " + tx + "px; background-color: " + color + "; border: 1px solid transparent; width: 3px; height: 3px; z-index: " + ijob + ";\"></div>");
var dotElem = $("<div class=\"dot\" style=\"top: " + ty + "px; left: " + tx + "px; background-color: " + color + "; z-index: " + ijob + ";\"></div>");
$("#minimap").append(dotElem);
function enable()
{
dotElem.css({ "border-color": color, "z-index": 9999, "width": "8px", "height": "8px", "margin-top": "-2px", "margin-left": "-3px" });
dotElem.addClass("active").css({ "border-color": color });
}
function disable()
{
dotElem.css({ "border-color": "transparent", "z-index": ijob, "width": "3px", "height": "3px", "margin-top": "0px", "margin-left": "0px", "filter": "" });
dotElem.removeClass("active").css({ "border-color": "transparent" });
}
function click(e)
@@ -177,11 +389,11 @@ function add(name, assignment, ijob, life_status, dam1, dam2, dam3, dam4, area,
}
trElem.on("mouseover", enable).on("mouseout", disable).on("click", click);
dotElem.on("mouseover", function()
{
trElem.addClass("hover");
enable();
trElem.scrollintoview();
}).on("mouseout", function()
{
trElem.removeClass("hover");