Merge pull request #11406 from kevinz000/minimaps

Ports station minimaps from Yogstation thank you monster860 you are an epic gamer
This commit is contained in:
Ghom
2020-03-12 14:18:39 +01:00
committed by GitHub
7 changed files with 202 additions and 1 deletions

View File

@@ -459,3 +459,6 @@
/datum/config_entry/number/max_bunker_days
config_entry_value = 7
min_val = 1
/datum/config_entry/flag/minimaps_enabled
config_entry_value = TRUE

View File

@@ -0,0 +1,20 @@
SUBSYSTEM_DEF(minimaps)
name = "Minimaps"
flags = SS_NO_FIRE
var/list/station_minimaps
var/datum/minimap_group/station_minimap
/datum/controller/subsystem/minimaps/Initialize()
if(!CONFIG_GET(flag/minimaps_enabled))
to_chat(world, "<span class='boldwarning'>Minimaps disabled! Skipping init.</span>")
return ..()
build_minimaps()
return ..()
/datum/controller/subsystem/minimaps/proc/build_minimaps()
station_minimaps = list()
for(var/z in SSmapping.levels_by_trait(ZTRAIT_STATION))
var/datum/space_level/SL = SSmapping.get_level(z)
var/name = (SL.name == initial(SL.name))? "[z] - Station" : "[z] - [SL.name]"
station_minimaps += new /datum/minimap(z, name = name)
station_minimap = new(station_minimaps, "Station")

View File

@@ -63,6 +63,9 @@
var/xenobiology_compatible = FALSE //Can the Xenobio management console transverse this area by default?
var/list/canSmoothWithAreas //typecache to limit the areas that atoms in this area can smooth with
/// Color on minimaps, if it's null (which is default) it makes one at random.
var/minimap_color
/**
* These two vars allow for multiple unique areas to be linked to a master area
* and share some functionalities such as APC powernet nodes, fire alarms etc, without sacrificing
@@ -96,7 +99,14 @@ GLOBAL_LIST_EMPTY(teleportlocs)
// ===
/area/New()
// This interacts with the map loader, so it needs to be set immediately
if(!minimap_color) // goes in New() because otherwise it doesn't fucking work
// generate one using the icon_state
if(icon_state && icon_state != "unknown")
var/icon/I = new(icon, icon_state, dir)
I.Scale(1,1)
minimap_color = I.GetPixel(1,1)
else // no icon state? use random.
minimap_color = rgb(rand(50,70),rand(50,70),rand(50,70)) // This interacts with the map loader, so it needs to be set immediately
// rather than waiting for atoms to initialize.
if (unique)
GLOB.areas_by_type[type] = src

View File

@@ -0,0 +1,10 @@
/client/verb/show_station_minimap()
set category = "OOC"
set name = "Show Station Minimap"
set desc = "Shows a minimap of the currently loaded station map."
if(!CONFIG_GET(flag/minimaps_enabled))
to_chat(usr, "<span class='boldwarning'>Minimap generation is not enabled in the server's configuration.</span>")
return
SSminimaps.station_minimap.show(src)

View File

@@ -0,0 +1,155 @@
/datum/minimap
var/name
var/icon/map_icon
var/icon/meta_icon
var/icon/overlay_icon
var/list/color_area_names = list()
var/minx
var/maxx
var/miny
var/maxy
var/z_level
var/id = 0
var/static/next_id = 0
/datum/minimap/New(z, x1 = 1, y1 = 1, x2 = world.maxx, y2 = world.maxy, name)
src.name = name
id = ++next_id
z_level = z
var/crop_x1 = x2
var/crop_x2 = x1
var/crop_y1 = y2
var/crop_y2 = y1
// do the generating
map_icon = new('html/blank.png')
meta_icon = new('html/blank.png')
map_icon.Scale(x2-x1+1, y2-y1+1) // arrays start at 1
meta_icon.Scale(x2-x1+1, y2-y1+1)
var/list/area_to_color = list()
for(var/turf/T in block(locate(x1,y1,z),locate(x2,y2,z)))
var/area/A = T.loc
var/img_x = T.x - x1 + 1 // arrays start at 1
var/img_y = T.y - y1 + 1
if(!istype(A, /area/space) || istype(T, /turf/closed/wall))
crop_x1 = min(crop_x1, T.x)
crop_x2 = max(crop_x2, T.x)
crop_y1 = min(crop_y1, T.y)
crop_y2 = max(crop_y2, T.y)
var/meta_color = area_to_color[A]
if(!meta_color)
meta_color = rgb(rand(0,255),rand(0,255),rand(0,255)) // technically conflicts could happen but it's like very unlikely and it's not that big of a deal if one happens
area_to_color[A] = meta_color
color_area_names[meta_color] = A.name
meta_icon.DrawBox(meta_color, img_x, img_y)
if(istype(T, /turf/closed/wall))
map_icon.DrawBox("#000000", img_x, img_y)
else if(!istype(A, /area/space))
var/color = A.minimap_color || "#FF00FF"
if(locate(/obj/machinery/power/solar) in T)
color = "#02026a"
if((locate(/obj/effect/spawner/structure/window) in T) || (locate(/obj/structure/grille) in T))
color = BlendRGB(color, "#000000", 0.5)
map_icon.DrawBox(color, img_x, img_y)
map_icon.Crop(crop_x1, crop_y1, crop_x2, crop_y2)
meta_icon.Crop(crop_x1, crop_y1, crop_x2, crop_y2)
minx = crop_x1
maxx = crop_x2
miny = crop_y1
maxy = crop_y2
overlay_icon = new(map_icon)
overlay_icon.Scale(16, 16)
/datum/minimap/proc/send(mob/user)
register_asset("minimap-[id].png", map_icon)
register_asset("minimap-[id]-meta.png", meta_icon)
send_asset_list(user, list("minimap-[id].png" = map_icon, "minimap-[id]-meta.png" = meta_icon), verify=FALSE)
/datum/minimap_group
var/list/minimaps
var/static/next_id = 0
var/id
var/name
/datum/minimap_group/New(list/maps, name)
id = ++next_id
src.name = name
minimaps = maps || list()
/datum/minimap_group/proc/show(mob/user)
if(!length(minimaps))
to_chat(user, "<span class='boldwarning'>ERROR: Attempted to access an empty datum/minimap_group. This should probably not happen.</span>")
return
var/list/datas = list()
var/list/info = list()
var/datum/minimap/first_map = minimaps[1]
for(var/i in 1 to length(minimaps))
var/datum/minimap/M = minimaps[i]
M.send(user)
info += "<img src='minimap-[M.id].png' id='map-[i]'><img src='minimap-[M.id]-meta.png' style='display: none' id='map-[i]-meta'><div id='label-[i]'></div>"
datas += json_encode(M.color_area_names);
info = info.Join()
var/html = {"
<!DOCTYPE html>
<HTML>
<HEAD>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<script>
function hexify(num) {
if(!num) num = 0;
num = num.toString(16);
if(num.length == 1) num = "0" + num;
return num;
}
window.onload = function() {
var datas = \[[jointext(datas, ",")]]
if(window.HTMLCanvasElement) {
for(var i = 0; i < [minimaps.len]; i++) {
(function() {
var data = datas\[i];
var img = document.getElementById("map-" + (i+1));
if(!img) return;
var canvas = document.createElement("canvas");
canvas.width = img.width * 2;
canvas.height = img.height * 2;
var ctx = canvas.getContext('2d');
ctx.msImageSmoothingEnabled = false;
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
img.parentNode.replaceChild(canvas, img);
ctx = document.createElement("canvas").getContext('2d');
ctx.canvas.width = img.width;
ctx.canvas.height = img.height;
ctx.drawImage(document.getElementById("map-" + (i+1) + "-meta"), 0, 0);
var imagedata = ctx.getImageData(0, 0, img.width, img.height);
var label = document.getElementById("label-" + (i+1));
canvas.onmousemove = function(e) {
var rect = canvas.getBoundingClientRect();
var x = Math.floor(e.offsetX * img.width / rect.width);
var y = Math.floor(e.offsetY * img.height / rect.height);
var color_idx = x * 4 + (y * 4 * imagedata.width);
var color = "#" + hexify(imagedata.data\[color_idx]) + hexify(imagedata.data\[color_idx+1]) + hexify(imagedata.data\[color_idx+2]);
label.textContent = data\[color];
canvas.title = data\[color];
}
canvas.onmouseout = function(e) {
label.textContent = "";
canvas.title = "";
}
})();
}
}
}
</script>
<STYLE>
img, canvas {
width: 100%
}
</STYLE>
<TITLE>[name]</TITLE>
</HEAD>
<BODY>[info]</BODY>
</HTML>"}
user << browse(html, "window=minimap_[id];size=768x[round(768 / first_map.map_icon.Width() * first_map.map_icon.Height() + 50)]")

BIN
html/blank.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 579 B

View File

@@ -269,6 +269,7 @@
#include "code\controllers\subsystem\mapping.dm"
#include "code\controllers\subsystem\materials.dm"
#include "code\controllers\subsystem\medals.dm"
#include "code\controllers\subsystem\minimaps.dm"
#include "code\controllers\subsystem\minor_mapping.dm"
#include "code\controllers\subsystem\mobs.dm"
#include "code\controllers\subsystem\moods.dm"
@@ -1679,6 +1680,7 @@
#include "code\modules\client\verbs\aooc.dm"
#include "code\modules\client\verbs\etips.dm"
#include "code\modules\client\verbs\looc.dm"
#include "code\modules\client\verbs\minimap.dm"
#include "code\modules\client\verbs\ooc.dm"
#include "code\modules\client\verbs\ping.dm"
#include "code\modules\client\verbs\suicide.dm"
@@ -2075,6 +2077,7 @@
#include "code\modules\lighting\lighting_turf.dm"
#include "code\modules\mapping\dmm_suite.dm"
#include "code\modules\mapping\map_template.dm"
#include "code\modules\mapping\minimaps.dm"
#include "code\modules\mapping\preloader.dm"
#include "code\modules\mapping\reader.dm"
#include "code\modules\mapping\ruins.dm"