mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-31 09:08:30 +01:00
Minimap support for the crew monitoring computer.
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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> </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;
|
||||
}
|
||||
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 |
Reference in New Issue
Block a user