mirror of
https://github.com/vgstation-coders/vgstation13.git
synced 2025-12-10 18:32:03 +00:00
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:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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*/
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user