Minimap support for the crew monitoring computer.

This commit is contained in:
NullQuery
2015-06-28 23:00:39 +02:00
parent a6ce6abfe3
commit c694febb77
10 changed files with 615 additions and 90 deletions
+5
View File
@@ -66,6 +66,7 @@ var/datum/subsystem/ticker/ticker
timeLeft = config.lobby_countdown * 10
world << "<B><FONT color='blue'>Welcome to the pre-game lobby!</FONT></B>"
world << "Please, setup your character and select ready. Game will start in [config.lobby_countdown] seconds"
crewmonitor.generateMiniMaps() // start generating minimaps (this is a background process)
current_state = GAME_STATE_PREGAME
if(GAME_STATE_PREGAME)
@@ -200,6 +201,10 @@ var/datum/subsystem/ticker/ticker
//Plus it provides an easy way to make cinematics for other events. Just use this as a template
/datum/subsystem/ticker/proc/station_explosion_cinematic(var/station_missed=0, var/override = null)
if( cinematic ) return //already a cinematic in progress!
for (var/datum/html_interface/hi in html_interfaces)
hi.closeAll()
auto_toggle_ooc(1) // Turn it on
//initialise our cinematic screen object
cinematic = new /obj/screen{icon='icons/effects/station_explosion.dmi';icon_state="station_intact";layer=20;mouse_opacity=0;screen_loc="1,0";}(src)
+9
View File
@@ -93,6 +93,9 @@
var/datum/atom_hud/data/medical/basic/B = huds[DATA_HUD_MEDICAL_BASIC]
B.update_suit_sensors(src)
var/turf/T = get_turf(src)
if (T) crewmonitor.queueUpdate(T.z)
//called when a carbon changes health
/mob/living/carbon/proc/med_hud_set_health()
var/image/holder = hud_list[HEALTH_HUD]
@@ -101,6 +104,9 @@
else
holder.icon_state = "hud[RoundHealth(health)]"
var/turf/T = get_turf(src)
if (T) crewmonitor.queueUpdate(T.z)
//called when a carbon changes stat, virus or XENO_HOST
/mob/living/carbon/proc/med_hud_set_status()
var/image/holder = hud_list[STATUS_HUD]
@@ -126,6 +132,9 @@
if(wear_id)
holder.icon_state = "hud[ckey(wear_id.GetJobName())]"
var/turf/T = get_turf(src)
if (T) crewmonitor.queueUpdate(T.z)
/mob/living/carbon/human/proc/sec_hud_set_implants()
var/image/holder
for(var/i in list(IMPTRACK_HUD, IMPLOYAL_HUD, IMPCHEM_HUD))
+100
View File
@@ -0,0 +1,100 @@
body
{
padding-left: 490px;
cursor: default;
}
#ntbgcenter
{
background-position: 550px 0px !important;
}
#minimap
{
position: fixed;
top: 8px;
left: 8px;
border: 2px inset #888;
}
#textbased
{
width: 100%;
}
#textbased table
{
min-width: 380px;
width: 100%;
table-layout: fixed;
}
#textbased td
{
vertical-align: top;
padding: 2px;
}
#textbased tbody tr:hover td, #textbased tbody tr.hover td
{
background-color: #434343;
}
#textarea:after
{
content: "";
clear: both;
}
a { display: none; }
.health
{
width: 16px;
background-color: #FFF;
border: 1px solid #434343;
position: relative;
top: 2px;
}
.health-5 { background-color: #17d568; }
.health-4 { background-color: #2ecc71; }
.health-3 { background-color: #e67e22; }
.health-2 { background-color: #ed5100; }
.health-1 { background-color: #e74c3c; }
.health-0 { background-color: #ed2814; }
.tt
{
position: relative;
display: inline-block;
height: 16px;
}
.tt > div
{
display: none;
}
.tt:hover > div
{
position: absolute;
bottom: -30px;
left: 50%;
margin-left: -64px;
display: block;
width: 128px;
height: 24px;
border: 1px solid #313131;
background-color: #434343;
padding: 4px;
z-index: 999;
text-align: center;
}
.tt > div > span
{
position: relative;
top: -2px;
}
+244 -73
View File
@@ -20,23 +20,15 @@
return
crewmonitor.show(user)
/obj/machinery/computer/crew/Topic(href, href_list)
if(..()) return
if (src.z > 6)
usr << "<span class='boldannounce'>Unable to establish a connection</span>: \black You're too far away from the station!"
return
if( href_list["close"] )
usr << browse(null, "window=crewcomp")
usr.unset_machine()
return
if(href_list["update"])
src.updateDialog()
return
var/global/datum/crewmonitor/crewmonitor = new
/datum/crewmonitor/var/list/jobs
/datum/crewmonitor/var/list/interfaces
/datum/crewmonitor
var/list/jobs
var/list/interfaces
var/list/data
var/const/MAX_ICON_DIMENSION = 1024
var/const/ICON_SIZE = 4
var/initialized = FALSE
/datum/crewmonitor/New()
. = ..()
@@ -84,6 +76,7 @@ var/global/datum/crewmonitor/crewmonitor = new
src.jobs = jobs
src.interfaces = list()
src.data = list()
/datum/crewmonitor/Destroy()
if (src.interfaces)
@@ -97,28 +90,53 @@ var/global/datum/crewmonitor/crewmonitor = new
if (!z) z = mob.z
if (z > 0 && src.interfaces)
if (!src.interfaces["[mob.z]"])
src.interfaces["[mob.z]"] = new/datum/html_interface/nanotrasen(src, "Crew Monitoring", 900, 600)
var/datum/html_interface/hi
src.update()
if (!src.interfaces["[z]"])
src.interfaces["[z]"] = new/datum/html_interface/nanotrasen(src, "Crew Monitoring", 900, 540, "<link rel=\"stylesheet\" type=\"text/css\" href=\"crewmonitor.css\" /><script type=\"text/javascript\">var z = [z]; var tile_size = [world.icon_size]; var maxx = [world.maxx]; var maxy = [world.maxy];</script><script type=\"text/javascript\" src=\"crewmonitor.js\"></script>")
var/datum/html_interface/hi = src.interfaces["[z]"]
hi = src.interfaces["[z]"]
hi.updateContent("content", "<a href=\"javascript:switchTo(0);\">Switch to mini map</a> <a href=\"javascript:switchTo(1);\">Switch to text-based</a><div id=\"minimap\"></div><div id=\"textbased\"></div>")
src.update(z, TRUE)
else
hi = src.interfaces["[z]"]
hi = src.interfaces["[z]"]
hi.show(mob)
src.updateFor(mob, hi, z)
/datum/crewmonitor/proc/update(z)
/datum/crewmonitor/proc/updateFor(hclient_or_mob, datum/html_interface/hi, z)
// This check will succeed if updateFor is called after showing to the player, but will fail
// on regular updates. Since we only really need this once we don't care if it fails.
var/list/parameters = list(ismob(hclient_or_mob) && isAI(hclient_or_mob) ? "true" : "false")
hi.callJavaScript("clearAll", parameters, hclient_or_mob)
for (var/list/L in data)
hi.callJavaScript("add", L, hclient_or_mob)
/datum/crewmonitor/proc/update(z, ignore_unused = FALSE)
if (src.interfaces["[z]"])
var/datum/html_interface/hi = src.interfaces["[z]"]
if (hi.isUsed())
var/t = "<table width='100%'><tr><td width='40%'><h3>Name</h3></td><td width='30%'><h3>Vitals</h3></td><td width='30%'><h3>Position</h3></td></tr>"
var/list/logs = list()
if (ignore_unused || hi.isUsed())
var/list/results = list()
var/obj/item/clothing/under/U
var/obj/item/weapon/card/id/I
var/log
var/turf/pos
var/style
var/ijob
var/damage_report
var/name
var/assignment
var/dam1
var/dam2
var/dam3
var/dam4
var/area
var/pos_x
var/pos_y
var/life_status
for(var/mob/living/carbon/human/H in mob_list)
// Check if their z-level is correct and if they are wearing a uniform.
@@ -133,61 +151,47 @@ var/global/datum/crewmonitor/crewmonitor = new
// Special case: If the mob is inside an object confirm the z-level on turf level.
if (H.z == 0 && (!pos || pos.z != z)) continue
log = ""
I = H.wear_id ? H.wear_id.GetID() : null
var/life_status = (H.stat > 1 ? "<span class=\"bad\">Deceased</span>" : "<span class=\"good\">Living</span>")
if (I)
style = null
name = I.registered_name
assignment = I.assignment
ijob = jobs[I.assignment]
if (ijob % 10 == 0) style += "font-weight: bold; " // head roles always end in 0
if (ijob >= 10 && ijob < 20) style += "color: #E74C3C; " // security
if (ijob >= 20 && ijob < 30) style += "color: #3498DB; " // medical
if (ijob >= 30 && ijob < 40) style += "color: #9B59B6; " // science
if (ijob >= 40 && ijob < 50) style += "color: #F1C40F; " // engineering
if (ijob >= 50 && ijob < 60) style += "color: #F39C12; " // cargo
if (ijob >= 200 && ijob < 230) style += "color: #00C100; " // Centcom
// ijob does not get displayed, nor does it take up space, it's just used for the positioning of an entry
log += "<span style=\"display: none\">[ijob]</span><tr><td width='40%'><span style=\"[style]\">[I.registered_name]</span> ([I.assignment])</td>"
else
log += "<span style=\"display: none\">80</span><tr><td width='40%'><i>Unknown</i></td>"
name = "<i>Unknown</i>"
assignment = ""
ijob = 80
damage_report = ""
if (U.sensor_mode >= 1) life_status = (!H.stat ? "true" : "false")
else life_status = null
if (U.sensor_mode > 1)
var/dam1 = round(H.getOxyLoss(),1)
var/dam2 = round(H.getToxLoss(),1)
var/dam3 = round(H.getFireLoss(),1)
var/dam4 = round(H.getBruteLoss(),1)
damage_report = "(<font color=\"#3498db\">[dam1]</font>/<font color=\"#2ecc71\">[dam2]</font>/<font color=\"#e67e22\">[dam3]</font>/<font color=\"#e74c3c\">[dam4]</font>)"
if (U.sensor_mode >= 2)
dam1 = round(H.getOxyLoss(),1)
dam2 = round(H.getToxLoss(),1)
dam3 = round(H.getFireLoss(),1)
dam4 = round(H.getBruteLoss(),1)
else
dam1 = null
dam2 = null
dam3 = null
dam4 = null
switch (U.sensor_mode)
if (1)
log += "<td width=\"30%\">[life_status]</td><td width=\"30%\"><span style=\"color:#7f8c8d\">Not Available</span></td></tr>"
if (U.sensor_mode >= 3)
if (!pos) pos = get_turf(H)
var/area/player_area = get_area(H)
if (2)
log += "<td width=\"30%\">[life_status] [damage_report]</td><td width=\"30%\"><span style=\"color:#7f8c8d\">Not Available</span></td></tr>"
area = format_text(player_area.name)
pos_x = pos.x
pos_y = pos.y
else
area = null
pos_x = null
pos_y = null
if (3)
if (!pos) pos = get_turf(H)
results[++results.len] = list(name, assignment, ijob, life_status, dam1, dam2, dam3, dam4, area, pos_x, pos_y, H.can_track(null))
var/area/player_area = get_area(H)
log += "<td width=\"30%\">[life_status] [damage_report]</td><td width=\"30%\">[format_text(player_area.name)] ([pos.x], [pos.y])</td></tr>"
logs.Add(log)
// TODO: Client-side sorting?
logs = sortList(logs)
for(log in logs)
t += log
t += "</table>"
hi.updateContent("content", t)
src.data = results
src.updateFor(null, hi, z) // updates for everyone
/datum/crewmonitor/proc/hiIsValidClient(datum/html_interface_client/hclient, datum/html_interface/hi)
var/z = ""
@@ -197,6 +201,32 @@ var/global/datum/crewmonitor/crewmonitor = new
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))) || (locate(/obj/item/device/sensor_device, hclient.client.mob.contents)) ) )
/datum/crewmonitor/Topic(href, href_list[], datum/html_interface_client/hclient)
if (istype(hclient))
if (hclient && hclient.client && hclient.client.mob && isAI(hclient.client.mob))
var/mob/living/silicon/ai/AI = hclient.client.mob
switch (href_list["action"])
if ("select_person")
AI.ai_camera_track(href_list["name"])
if ("select_position")
var/x = text2num(href_list["x"])
var/y = text2num(href_list["y"])
var/turf/tile = locate(x, y, AI.z)
var/obj/machinery/camera/C = locate(/obj/machinery/camera) in range(5, tile)
if (!C) C = locate(/obj/machinery/camera) in range(10, tile)
if (!C) C = locate(/obj/machinery/camera) in range(15, tile)
if (C)
var/turf/current_loc = AI.eyeobj.loc
spawn(min(30, get_dist(get_turf(C), AI.eyeobj) / 4))
if (AI && AI.eyeobj && current_loc == AI.eyeobj.loc)
AI.switchCamera(C)
/*
/proc/crewscan()
var/list/tracked = list()
@@ -214,7 +244,148 @@ var/global/datum/crewmonitor/crewmonitor = new
. = ..()
if (old_z != src.z) procqueue.queue(crewmonitor, "update", old_z)
procqueue.queue(crewmonitor, "update", src.z)
if (old_z != src.z) crewmonitor.queueUpdate(old_z)
crewmonitor.queueUpdate(src.z)
else
return ..()
return ..()
/datum/crewmonitor/proc/queueUpdate(z)
procqueue.queue(crewmonitor, "update", z)
/datum/crewmonitor/proc/generateMiniMaps()
spawn
for (var/z = 1 to world.maxz) src.generateMiniMap(z)
NOTICE("MINIMAP: All minimaps have been generated.")
for (var/client/C in clients)
src.sendResources(C)
src.initialized = TRUE
/datum/crewmonitor/proc/sendResources(client/C)
C << browse_rsc('crew.js', "crewmonitor.js")
C << browse_rsc('crew.css', "crewmonitor.css")
for (var/z = 1 to world.maxz) C << browse_rsc(file("[getMinimapFile(z)].png"), "minimap_[z].png")
/datum/crewmonitor/proc/getMinimapFile(z)
return "data/minimaps/map_[z]"
// Activate this to debug tile mismatches in the minimap.
// This will store the full information on each tile and compare it the next time you run the minimap.
// It can be used to find out what's changed since the last iteration.
// Only activate this when you need it - this should never be active on a live server!
// #define MINIMAP_DEBUG
/datum/crewmonitor/proc/generateMiniMap(z, x1 = 1, y1 = 1, x2 = world.maxx, y2 = world.maxy)
var/result_path = "[src.getMinimapFile(z)].png"
var/hash_path = "[src.getMinimapFile(z)].md5"
var/list/tiles = block(locate(x1, y1, z), locate(x2, y2, z))
var/hash = ""
var/temp
#ifdef MINIMAP_DEBUG
var/tiledata_path = "data/minimaps/debug_tiledata_[z].sav"
var/savefile/F = new/savefile(tiledata_path)
#endif
// Note for future developer: If you have tiles on the map with random or dynamic icons this hash check will fail
// every time. You'll have to modify this code to generate a unique hash for your object.
// Don't forget to modify the minimap generation code to use a default icon (or skip generation altogether).
for (var/turf/tile in tiles)
if (istype(tile.loc, /area/asteroid) || istype(tile.loc, /area/mine/unexplored) || istype(tile, /turf/simulated/mineral) || (istype(tile.loc, /area/space) && istype(tile, /turf/simulated/floor/plating/asteroid)))
temp = "/area/asteroid"
else if (istype(tile.loc, /area/mine) && istype(tile, /turf/simulated/floor/plating/asteroid))
temp = "/area/mine/explored"
else if (tile.type == /area/start && tile.type == /turf/space || istype(tile, /turf/space/transit))
temp = "/turf/space"
else if (tile.type == /turf/simulated/floor/plating/abductor)
temp = "/turf/simulated/floor/plating/abductor"
else
temp = "[tile.icon][tile.icon_state][tile.dir]"
#ifdef MINIMAP_DEBUG
if (F["/[tile.y]/[tile.x]"] && F["/[tile.y]/[tile.x]"] != temp)
CRASH("Mismatch: [tile.type] at [tile.x],[tile.y],[tile.z] ([tile.icon], [tile.icon_state], [tile.dir])")
else
F["/[tile.y]/[tile.x]"] << temp
#endif
hash = md5("[hash][temp]")
if (fexists(result_path))
if (!fexists(hash_path) || trim(file2text(hash_path)) != hash)
fdel(result_path)
fdel(hash_path)
if (!fexists(result_path))
ASSERT(x1 > 0)
ASSERT(y1 > 0)
ASSERT(x2 <= world.maxx)
ASSERT(y2 <= world.maxy)
var/icon/map_icon = new/icon('html/mapbase1024.png')
// map_icon is fine and contains only 1 direction at this point.
ASSERT(map_icon.Width() == MAX_ICON_DIMENSION && map_icon.Height() == MAX_ICON_DIMENSION)
NOTICE("MINIMAP: Generating minimap for z-level [z].")
var/i = 0
var/icon/turf_icon
var/old_icon
var/old_icon_state
var/old_dir
var/new_icon
var/new_icon_state
var/new_dir
for (var/turf/tile in tiles)
if (tile.type != /area/start && tile.type != /turf/space && !istype(tile, /turf/space/transit))
if (istype(tile.loc, /area/asteroid) || istype(tile.loc, /area/mine/unexplored) || istype(tile, /turf/simulated/mineral) || (istype(tile.loc, /area/space) && istype(tile, /turf/simulated/floor/plating/asteroid)))
new_icon = 'icons/turf/mining.dmi'
new_icon_state = "rock"
new_dir = 2
else if (istype(tile.loc, /area/mine) && istype(tile, /turf/simulated/floor/plating/asteroid))
new_icon = 'icons/turf/floors.dmi'
new_icon_state = "asteroid"
new_dir = 2
else if (tile.type == /turf/simulated/floor/plating/abductor)
new_icon = 'icons/turf/floors.dmi'
new_icon_state = "alienpod1"
new_dir = 2
else
new_icon = tile.icon
new_icon_state = tile.icon_state
new_dir = tile.dir
if (new_icon != old_icon || new_icon_state != old_icon_state || new_dir != old_dir)
old_icon = new_icon
old_icon_state = new_icon_state
old_dir = new_dir
turf_icon = new/icon(new_icon, new_icon_state, new_dir, 1, 0)
turf_icon.Scale(ICON_SIZE, ICON_SIZE)
map_icon.Blend(turf_icon, ICON_OVERLAY, ((tile.x - 1) * ICON_SIZE), ((tile.y - 1) * ICON_SIZE))
if ((++i) % 512 == 0) sleep(1) // deliberate delay to avoid lag spikes
if ((i % 1024) == 0) NOTICE("MINIMAP: Generated [i] of [tiles.len] tiles.")
else
sleep(-1) // avoid sleeping if possible: prioritize pending procs
NOTICE("MINIMAP: Generated [tiles.len] of [tiles.len] tiles.")
// BYOND BUG: map_icon now contains 4 directions? Create a new icon with only a single state.
var/icon/result_icon = new/icon()
result_icon.Insert(map_icon, "", SOUTH, 1, 0)
fcopy(result_icon, result_path)
text2file(hash, hash_path)
#ifdef MINIMAP_DEBUG
#undef MINIMAP_DEBUG
#endif
+196
View File
@@ -0,0 +1,196 @@
var isAI = null;
var scale_x;
var scale_y;
function disableSelection(){ return false; };
$(window).on("onUpdateContent", function()
{
$("#textbased").html("<table><colgroup><col /><col style=\"width: 24px;\" /><col style=\"width: 180px;\" /></colgroup><thead><tr><td><h3>Name</h3></td><td><h3>&nbsp;</h3></td><td><h3>Position</h3></td></tr></thead><tbody id=\"textbased-tbody\"></tbody></table>");
$("#minimap").append("<img src=\"minimap_" + z + ".png\" id=\"map\" style=\"width: auto; height: 480px;\" />");
$("body")[0].onselectstart = disableSelection;
var width = $("#minimap").width();
scale_x = width / (maxx * tile_size);
scale_y = width / (maxy * tile_size); // height is assumed to be the same
$("#minimap").on("click", function(e)
{
var x = ((((e.clientX - 8) / scale_x) / tile_size) + 1).toFixed(0);
var y = ((maxy - (((e.clientY - 8) / scale_y) / tile_size)) + 1).toFixed(0);
window.location.href = "byond://?src=" + hSrc + "&action=select_position&x=" + x + "&y=" + y;
});
});
var updateMap = true;
function switchTo(i)
{
if (i == 1)
{
$("#minimap").hide();
$("#textbased").show();
}
else
{
$("#textbased").hide();
$("#minimap").show();
}
}
function clearAll(ai)
{
if (isAI === null) { isAI = (ai == "true"); }
$("#textbased-tbody").empty();
$("#minimap .dot").remove();
}
function isHead(ijob)
{
return (ijob % 10 == 0); // head roles always end in 0
}
function getColor(ijob)
{
if (ijob >= 10 && ijob < 20) { return "#E74C3C"; } // security
else if (ijob >= 20 && ijob < 30) { return "#3498DB"; } // medical
else if (ijob >= 30 && ijob < 40) { return "#9B59B6"; } // science
else if (ijob >= 40 && ijob < 50) { return "#F1C40F"; } // engineering
else if (ijob >= 50 && ijob < 60) { return "#F39C12"; } // cargo
else if (ijob >= 200 && ijob < 230) { return "#00C100"; } // Centcom
}
function add(name, assignment, ijob, life_status, dam1, dam2, dam3, dam4, area, pos_x, pos_y, in_range)
{
try { ijob = parseInt(ijob); }
catch (ex) { ijob = 0; }
var ls = "";
if (life_status === null) { ls = (life_status ? "<span class=\"bad\">Deceased</span>" : "<span class=\"good\">Living</span>"); }
var healthHTML = "";
if (dam1 != "" || dam2 != "" || dam3 != "" || dam4 != "")
{
var avg_dam = parseInt(dam1) + parseInt(dam2) + parseInt(dam3) + parseInt(dam4);
var i;
if (isAI) { i = -1; }
else
{
if (avg_dam <= 0) { i = 5; }
else if (avg_dam <= 25) { i = 4; }
else if (avg_dam <= 50) { i = 3; }
else if (avg_dam <= 75) { i = 2; }
else { i = 0; }
}
healthHTML = "<div class=\"health health-" + i + " tt\"><div><span>(<font color=\"#3498db\">" + dam1 + "</font>/<font color=\"#2ecc71\">" + dam2 + "</font>/<font color=\"#e67e22\">" + dam3 + "</font>/<font color=\"#e74c3c\">" + dam4 + "</font>)</span></div></div>";
}
else
{
healthHTML = "<div class=\"health health-" + (life_status == "" ? -1 : (life_status == "true" ? 4 : 0)) + " tt\"><div><span>Not Available</span></div></div>";
}
var trElem = $("<tr></tr>").attr("data-ijob", ijob);
var tdElem;
var spanElem;
tdElem = $("<td></td>");
var italics = false;
if (name.length >= 7 && name.substring(0, 3) == "<i>")
{
name = name.substring(3, name.length - 4);
italics = true;
}
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);
if (assignment) { tdElem.append($("<span></span>").text(" (" + assignment + ")")); }
trElem.append(tdElem);
tdElem = $("<td style=\"text-align: center; vertical-align: top; cursor: default;\"></td>");
tdElem.html(healthHTML);
trElem.append(tdElem);
tdElem = $("<td style=\"cursor: default;\"></td>");
if (area && pos_x && pos_y) { tdElem.append($("<div></div>").text(area).addClass("tt").append($("<div></div>").append($("<span></span>").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);
if (!color) { color = "#FFFFFF"; }
var dotElem = $("<div class=\"dot\" style=\"position: absolute; top: " + ty + "px; left: " + tx + "px; background-color: " + color + "; border: 1px solid transparent; width: 3px; height: 3px; z-index: " + ijob + ";\"></div>");
$("#minimap").append(dotElem);
function enable()
{
dotElem.css({ "border-color": "#FFFFFF", "z-index": 9999, "width": "6px", "height": "6px", "margin-top": "-1px", "margin-left": "-2px" });
}
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;
}
+5
View File
@@ -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(
+49 -16
View File
@@ -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
@@ -201,6 +221,8 @@ mob/verb/test()
hclient.client << output(replacetextEx(replacetextEx(file2text('html_interface.html'), "\[hsrc\]", "\ref[src]"), "</head>", "[head]</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)
@@ -244,12 +266,22 @@ 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)
@@ -269,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)
@@ -280,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.
@@ -290,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.
@@ -312,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)
@@ -11,6 +11,12 @@ body
line-height: 170%; /* NullQuery: 170% of what? */
}
/* Fix for IE8 */
body
{
background-color: #1F1F1F\9 !important;
}
#ntbgcenter
{
position: absolute;
+1 -1
View File
@@ -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
Binary file not shown.

After

Width:  |  Height:  |  Size: 513 KiB