diff --git a/code/__defines/holomap.dm b/code/__defines/holomap.dm new file mode 100644 index 0000000000..6bcb601b44 --- /dev/null +++ b/code/__defines/holomap.dm @@ -0,0 +1,49 @@ +// +// Constants and standard colors for the holomap +// + +#define WORLD_ICON_SIZE 32 // Size of a standard tile in pixels (world.icon_size) +#define PIXEL_MULTIPLIER WORLD_ICON_SIZE/32 // Convert from normal icon size of 32 to whatever insane thing this server is using. +#define HOLOMAP_ICON 'icons/480x480_vr.dmi' // Icon file to start with when drawing holomaps (to get a 480x480 canvas). +#define ui_holomap "CENTER-7, CENTER-7" // Screen location of the holomap "hud" + +// Holomap colors +#define HOLOMAP_OBSTACLE "#FFFFFFDD" // Color of walls and barriers +#define HOLOMAP_PATH "#66666699" // Color of floors +#define HOLOMAP_ROCK "#66666644" // Color of mineral walls +#define HOLOMAP_HOLOFIER "#79FF79" // Whole map is multiplied by this to give it a green holoish look + +#define HOLOMAP_AREACOLOR_COMMAND "#0000F099" +#define HOLOMAP_AREACOLOR_SECURITY "#AE121299" +#define HOLOMAP_AREACOLOR_MEDICAL "#447FC299" +#define HOLOMAP_AREACOLOR_SCIENCE "#A154A699" +#define HOLOMAP_AREACOLOR_ENGINEERING "#F1C23199" +#define HOLOMAP_AREACOLOR_CARGO "#E06F0099" +#define HOLOMAP_AREACOLOR_HALLWAYS "#FFFFFF66" +#define HOLOMAP_AREACOLOR_ARRIVALS "#0000FFCC" +#define HOLOMAP_AREACOLOR_ESCAPE "#FF0000CC" +#define HOLOMAP_AREACOLOR_DORMS "#CCCC0099" + +// Handy defines to lookup the pixel offsets for this Z-level. Cache these if you use them in a loop tho. +#define HOLOMAP_PIXEL_OFFSET_X(zLevel) ((using_map.holomap_offset_x.len >= zLevel) ? using_map.holomap_offset_x[zLevel] : 0) +#define HOLOMAP_PIXEL_OFFSET_Y(zLevel) ((using_map.holomap_offset_y.len >= zLevel) ? using_map.holomap_offset_y[zLevel] : 0) +#define HOLOMAP_LEGEND_X(zLevel) ((using_map.holomap_legend_x.len >= zLevel) ? using_map.holomap_legend_x[zLevel] : 96) +#define HOLOMAP_LEGEND_Y(zLevel) ((using_map.holomap_legend_y.len >= zLevel) ? using_map.holomap_legend_y[zLevel] : 96) + +// VG stuff we probably won't use +// #define HOLOMAP_FILTER_DEATHSQUAD 1 +// #define HOLOMAP_FILTER_ERT 2 +// #define HOLOMAP_FILTER_NUKEOPS 4 +// #define HOLOMAP_FILTER_ELITESYNDICATE 8 +// #define HOLOMAP_FILTER_VOX 16 +// #define HOLOMAP_FILTER_STATIONMAP 32 +// #define HOLOMAP_FILTER_STATIONMAP_STRATEGIC 64//features markers over the captain's office, the armory, the SMES + +// #define HOLOMAP_MARKER_SMES "smes" +// #define HOLOMAP_MARKER_DISK "diskspawn" +// #define HOLOMAP_MARKER_SKIPJACK "skipjack" +// #define HOLOMAP_MARKER_SYNDISHUTTLE "syndishuttle" + +#define HOLOMAP_EXTRA_STATIONMAP "stationmapformatted" +#define HOLOMAP_EXTRA_STATIONMAPAREAS "stationareas" +#define HOLOMAP_EXTRA_STATIONMAPSMALL "stationmapsmall" \ No newline at end of file diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm index 45c6f7e277..7a7d82d175 100644 --- a/code/_onclick/hud/hud.dm +++ b/code/_onclick/hud/hud.dm @@ -12,7 +12,8 @@ var/list/global_huds = list( global_hud.nvg, global_hud.thermal, global_hud.meson, - global_hud.science + global_hud.science, + global_hud.holomap ) /datum/hud/var/obj/screen/grab_intent @@ -30,6 +31,7 @@ var/list/global_huds = list( var/obj/screen/thermal var/obj/screen/meson var/obj/screen/science + var/obj/screen/holomap /datum/global_hud/proc/setup_overlay(var/icon_state) var/obj/screen/screen = new /obj/screen() @@ -69,6 +71,18 @@ var/list/global_huds = list( meson = setup_overlay("meson_hud") science = setup_overlay("science_hud") + // The holomap screen object is actually totally invisible. + // Station maps work by setting it as an images location before sending to client, not + // actually changing the icon or icon state of the screen object itself! + // Why do they work this way? I don't know really, that is how /vg designed them, but since they DO + // work this way, we can take advantage of their immutability by making them part of + // the global_hud (something we have and /vg doesn't) instead of an instance per mob. + holomap = new /obj/screen() + holomap.name = "holomap" + holomap.icon = null + holomap.screen_loc = ui_holomap + holomap.mouse_opacity = 0 + var/obj/screen/O var/i //that nasty looking dither you get when you're short-sighted diff --git a/code/modules/holomap/generate_holomap.dm b/code/modules/holomap/generate_holomap.dm new file mode 100644 index 0000000000..9783fee656 --- /dev/null +++ b/code/modules/holomap/generate_holomap.dm @@ -0,0 +1,204 @@ +// +// Holomap generation. +// Based on /vg/station but trimmed down (without antag stuff) and massively optimized (you should have seen it before!) ~Leshana +// + +// Define what criteria makes a turf a path or not + +// Hack because we don't have catwalks +/obj/structure/catwalk + name = "catwalk" +// End hack + +// Turfs that will be colored as HOLOMAP_ROCK +#define IS_ROCK(tile) (istype(tile, /turf/simulated/mineral) && tile.density) + +// Turfs that will be colored as HOLOMAP_OBSTACLE +#define IS_OBSTACLE(tile) ((!istype(tile, /turf/space) && istype(tile.loc, /area/mine/unexplored)) \ + || istype(tile, /turf/simulated/wall) \ + || istype(tile, /turf/unsimulated/mineral) \ + || (istype(tile, /turf/unsimulated/wall) && !istype(tile, /turf/unsimulated/wall/planetary)) \ + /*|| istype(tile, /turf/simulated/shuttle/wall)*/ \ + || (locate(/obj/structure/grille) in tile) \ + /*|| (locate(/obj/structure/window/full) in tile)*/) + +// Turfs that will be colored as HOLOMAP_PATH +#define IS_PATH(tile) ((istype(tile, /turf/simulated/floor) && !istype(tile, /turf/simulated/floor/outdoors)) \ + || istype(tile, /turf/unsimulated/floor) \ + /*|| istype(tile, /turf/simulated/shuttle/floor)*/ \ + || (locate(/obj/structure/catwalk) in tile)) + + +// WARNING - TOTAL HACK - HOOKING INIT +/datum/controller/game_controller/setup_objects() + ..() + generateHoloMinimaps() + +/// Generates all the holo minimaps, initializing it all nicely, probably. +// TODO - This should be a subsystem ~Leshana +var/global/holomaps_initialized = FALSE +var/global/list/holoMiniMaps = list() +var/global/list/extraMiniMaps = list() +/proc/generateHoloMinimaps() + var/start_time = world.timeofday + // Build the base map for each z level + for (var/z = 1 to world.maxz) + global.holoMiniMaps |= z // hack, todo fix + global.holoMiniMaps[z] = generateHoloMinimap(z) + + // Generate the area overlays, small maps, etc for the station levels. + for (var/z in using_map.station_levels) + generateStationMinimap(z) + + if(using_map.holomap_smoosh) + for(var/smoosh_list in using_map.holomap_smoosh) + smooshTetherHolomaps(smoosh_list) + + global.holomaps_initialized = TRUE + admin_notice("Holomaps initialized in [round(0.1*(world.timeofday-start_time),0.1)] seconds.", R_DEBUG) + + // TODO - Check - They had a delayed init perhaps? + for (var/obj/machinery/station_map/S in station_holomaps) + S.initialize() + +// Generates the "base" holomap for one z-level, showing only the physical structure of walls and paths. +/proc/generateHoloMinimap(var/zLevel = 1) + //log_debug("Generating base minimap for z=[zLevel]") + // Save these values now to avoid a bazillion array lookups + var/offset_x = HOLOMAP_PIXEL_OFFSET_X(zLevel) + var/offset_y = HOLOMAP_PIXEL_OFFSET_Y(zLevel) + + // Sanity checks - Better to generate a helpful error message now than have DrawBox() runtime + var/icon/canvas = icon(HOLOMAP_ICON, "blank") + if(world.maxx + offset_x > canvas.Width()) + crash_with("Minimap for z=[zLevel] : world.maxx ([world.maxx]) + holomap_offset_x ([offset_x]) must be <= [canvas.Width()]") + if(world.maxy + offset_y > canvas.Height()) + crash_with("Minimap for z=[zLevel] : world.maxy ([world.maxy]) + holomap_offset_y ([offset_y]) must be <= [canvas.Height()]") + + for(var/x = 1 to world.maxx) + for(var/y = 1 to world.maxy) + var/turf/tile = locate(x, y, zLevel) + if(tile && tile.loc:holomapAlwaysDraw()) + if(IS_ROCK(tile)) + canvas.DrawBox(HOLOMAP_ROCK, x + offset_x, y + offset_y) + if(IS_OBSTACLE(tile)) + canvas.DrawBox(HOLOMAP_OBSTACLE, x + offset_x, y + offset_y) + else if(IS_PATH(tile)) + canvas.DrawBox(HOLOMAP_PATH, x + offset_x, y + offset_y) + // Check sleeping after each row to avoid *completely* destroying the server + if(world.tick_usage >= 80) sleep(world.tick_lag * 0.2) + return canvas + +// Okay, what does this one do? +// This seems to do the drawing thing, but draws only the areas, having nothing to do with the tiles. +// Leshana: I'm guessing this map will get overlayed on top of the base map at runtime? We'll see. +// Wait, seems we actually blend the area map on top of it right now! Huh. +// It does a bunch of other stuff too tho, lets check what that is. +/proc/generateStationMinimap(var/zLevel) + //log_debug("Generating station minimap for z=[zLevel]") + // Save these values now to avoid a bazillion array lookups + var/offset_x = HOLOMAP_PIXEL_OFFSET_X(zLevel) + var/offset_y = HOLOMAP_PIXEL_OFFSET_Y(zLevel) + + // Sanity checks - Better to generate a helpful error message now than have DrawBox() runtime + var/icon/canvas = icon(HOLOMAP_ICON, "blank") + if(world.maxx + offset_x > canvas.Width()) + crash_with("Minimap for z=[zLevel] : world.maxx ([world.maxx]) + holomap_offset_x ([offset_x]) must be <= [canvas.Width()]") + if(world.maxy + offset_y > canvas.Height()) + crash_with("Minimap for z=[zLevel] : world.maxy ([world.maxy]) + holomap_offset_y ([offset_y]) must be <= [canvas.Height()]") + + for(var/x = 1 to world.maxx) + for(var/y = 1 to world.maxy) + var/turf/tile = locate(x, y, zLevel) + if(tile && tile.loc) + var/area/areaToPaint = tile.loc + if(areaToPaint.holomap_color) + canvas.DrawBox(areaToPaint.holomap_color, x + offset_x, y + offset_y) + + // Save this nice area-colored canvas in case we want to layer it or something I guess + extraMiniMaps["[HOLOMAP_EXTRA_STATIONMAPAREAS]_[zLevel]"] = canvas + + var/icon/map_base = icon(holoMiniMaps[zLevel]) + map_base.Blend(HOLOMAP_HOLOFIER, ICON_MULTIPLY) + + // Generate the full sized map by blending the base and areas onto the backdrop + var/icon/big_map = icon(HOLOMAP_ICON, "stationmap") + big_map.Blend(map_base, ICON_OVERLAY) + big_map.Blend(canvas, ICON_OVERLAY) + extraMiniMaps["[HOLOMAP_EXTRA_STATIONMAP]_[zLevel]"] = big_map + + // Generate the "small" map (I presume for putting on wall map things?) + var/icon/small_map = icon(HOLOMAP_ICON, "blank") + small_map.Blend(map_base, ICON_OVERLAY) + small_map.Blend(canvas, ICON_OVERLAY) + small_map.Scale(WORLD_ICON_SIZE, WORLD_ICON_SIZE) + + // And rotate it in every direction of course! + var/icon/actual_small_map = icon(small_map) + actual_small_map.Insert(new_icon = small_map, dir = SOUTH) + actual_small_map.Insert(new_icon = turn(small_map, 90), dir = WEST) + actual_small_map.Insert(new_icon = turn(small_map, 180), dir = NORTH) + actual_small_map.Insert(new_icon = turn(small_map, 270), dir = EAST) + extraMiniMaps["[HOLOMAP_EXTRA_STATIONMAPSMALL]_[zLevel]"] = actual_small_map + +// For tiny multi-z maps like the tether, we want to smoosh em together into a nice big one! +/proc/smooshTetherHolomaps(var/list/zlevels) + var/icon/big_map = icon(HOLOMAP_ICON, "stationmap") + var/icon/small_map = icon(HOLOMAP_ICON, "blank") + // For each zlevel in turn, overlay them on top of each other + for(var/zLevel in zlevels) + var/icon/z_terrain = icon(holoMiniMaps[zLevel]) + z_terrain.Blend(HOLOMAP_HOLOFIER, ICON_MULTIPLY) + big_map.Blend(z_terrain, ICON_OVERLAY) + small_map.Blend(z_terrain, ICON_OVERLAY) + var/icon/z_areas = extraMiniMaps["[HOLOMAP_EXTRA_STATIONMAPAREAS]_[zLevel]"] + big_map.Blend(z_areas, ICON_OVERLAY) + small_map.Blend(z_areas, ICON_OVERLAY) + + // Then scale and rotate to make the actual small map we will use + small_map.Scale(WORLD_ICON_SIZE, WORLD_ICON_SIZE) + var/icon/actual_small_map = icon(small_map) + actual_small_map.Insert(new_icon = small_map, dir = SOUTH) + actual_small_map.Insert(new_icon = turn(small_map, 90), dir = WEST) + actual_small_map.Insert(new_icon = turn(small_map, 180), dir = NORTH) + actual_small_map.Insert(new_icon = turn(small_map, 270), dir = EAST) + + // Then assign this icon as the icon for all those levels! + for(var/zLevel in zlevels) + extraMiniMaps["[HOLOMAP_EXTRA_STATIONMAP]_[zLevel]"] = big_map + extraMiniMaps["[HOLOMAP_EXTRA_STATIONMAPSMALL]_[zLevel]"] = actual_small_map + +// +// ## Debugging and Testing ## +// + +/client/verb/debug_map() + set category = "Debug" + set name = "Debug Map Datum" + debug_variables(using_map) + +// TODO - Holomap Markers! +// /proc/generateMinimapMarkers(var/zLevel) +// // Save these values now to avoid a bazillion array lookups +// var/offset_x = HOLOMAP_PIXEL_OFFSET_X(zLevel) +// var/offset_y = HOLOMAP_PIXEL_OFFSET_Y(zLevel) + +// // TODO - Holomap markers +// for(var/filter in list(HOLOMAP_FILTER_STATIONMAP)) +// var/icon/canvas = icon(HOLOMAP_ICON, "blank") +// for(/datum/holomap_marker/holomarker in holomap_markers) +// if(holomarker.z == zLevel && holomarker.filter & filter) +// canvas.Blend(icon(holomarker.icon, holomarker.icon_state), ICON_OVERLAY, holomarker.x + offset_x, holomarker.y + offset_y) +// extraMiniMaps["[HOLOMAP_EXTRA_MARKERS]_[filter]_[zLevel]"] = canvas + +// /datum/holomap_marker +// var/x +// var/y +// var/z +// var/filter +// var/icon = 'icons/holomap_markers.dmi' +// var/icon_state + +#undef IS_ROCK +#undef IS_OBSTACLE +#undef IS_PATH diff --git a/code/modules/holomap/holomap_area.dm b/code/modules/holomap/holomap_area.dm new file mode 100644 index 0000000000..7ea09dcd21 --- /dev/null +++ b/code/modules/holomap/holomap_area.dm @@ -0,0 +1,78 @@ +/* +** Holomap vars and procs on /area +*/ + +/area + var/holomap_color = null // Color of this area on station holomap + +/area/rnd + holomap_color = HOLOMAP_AREACOLOR_SCIENCE +/area/outpost/research + holomap_color = HOLOMAP_AREACOLOR_SCIENCE +/area/server + holomap_color = HOLOMAP_AREACOLOR_SCIENCE +/area/assembly + holomap_color = HOLOMAP_AREACOLOR_SCIENCE + +/area/bridge + holomap_color = HOLOMAP_AREACOLOR_COMMAND +/area/teleporter + holomap_color = HOLOMAP_AREACOLOR_COMMAND +/area/teleporter/departing + holomap_color = null + +/area/security + holomap_color = HOLOMAP_AREACOLOR_SECURITY +/area/tether/surfacebase/security + holomap_color = HOLOMAP_AREACOLOR_SECURITY + +/area/medical + holomap_color = HOLOMAP_AREACOLOR_MEDICAL +/area/tether/surfacebase/medical + holomap_color = HOLOMAP_AREACOLOR_MEDICAL + +/area/engineering + holomap_color = HOLOMAP_AREACOLOR_ENGINEERING +/area/maintenance/substation/engineering + holomap_color = HOLOMAP_AREACOLOR_ENGINEERING +/area/storage/tech + holomap_color = HOLOMAP_AREACOLOR_ENGINEERING + +/area/quartermaster + holomap_color = HOLOMAP_AREACOLOR_CARGO +/area/tether/surfacebase/mining_main + holomap_color = HOLOMAP_AREACOLOR_CARGO + +/area/hallway + holomap_color = HOLOMAP_AREACOLOR_HALLWAYS +/area/bridge/hallway + holomap_color = HOLOMAP_AREACOLOR_HALLWAYS + +/area/crew_quarters/sleep + holomap_color = HOLOMAP_AREACOLOR_DORMS +/area/crew_quarters/sleep/cryo + holomap_color = null + +// Heads +/area/crew_quarters/captain + holomap_color = HOLOMAP_AREACOLOR_COMMAND +/area/crew_quarters/heads/hop + holomap_color = HOLOMAP_AREACOLOR_COMMAND +/area/crew_quarters/heads/hor + holomap_color = HOLOMAP_AREACOLOR_SCIENCE +/area/crew_quarters/heads/chief + holomap_color = HOLOMAP_AREACOLOR_ENGINEERING +/area/crew_quarters/heads/hos + holomap_color = HOLOMAP_AREACOLOR_SECURITY +/area/crew_quarters/heads/cmo + holomap_color = HOLOMAP_AREACOLOR_MEDICAL +/area/crew_quarters/medbreak + holomap_color = HOLOMAP_AREACOLOR_MEDICAL + + +// ### PROCS ### +// Whether the turfs in the area should be drawn onto the "base" holomap. +/area/proc/holomapAlwaysDraw() + return TRUE +/area/shuttle/holomapAlwaysDraw() + return FALSE \ No newline at end of file diff --git a/code/modules/holomap/holomap_datum.dm b/code/modules/holomap/holomap_datum.dm new file mode 100644 index 0000000000..67a1ee0bc9 --- /dev/null +++ b/code/modules/holomap/holomap_datum.dm @@ -0,0 +1,40 @@ +// Simple datum to keep track of a running holomap. Each machine capable of displaying the holomap will have one. +/datum/station_holomap + var/image/station_map + var/image/cursor + var/image/legend + +/datum/station_holomap/proc/initialize_holomap(var/turf/T, var/isAI = null, var/mob/user = null, var/reinit = FALSE) + if(!station_map || reinit) + station_map = image(extraMiniMaps["[HOLOMAP_EXTRA_STATIONMAP]_[T.z]"]) + if(!cursor || reinit) + cursor = image('icons/holomap_markers_vr.dmi', "you") + if(!legend || reinit) + legend = image('icons/effects/64x64_vr.dmi', "legend") + + if(isAI) + T = get_turf(user.client.eye) + cursor.pixel_x = (T.x - 6 + HOLOMAP_PIXEL_OFFSET_X(T.z)) * PIXEL_MULTIPLIER + cursor.pixel_y = (T.y - 6 + HOLOMAP_PIXEL_OFFSET_Y(T.z)) * PIXEL_MULTIPLIER + + legend.pixel_x = HOLOMAP_LEGEND_X(T.z) + legend.pixel_y = HOLOMAP_LEGEND_Y(T.z) + + station_map.overlays |= cursor + station_map.overlays |= legend + +/datum/station_holomap/proc/initialize_holomap_bogus() + station_map = image('icons/480x480_vr.dmi', "stationmap") + legend = image('icons/effects/64x64_vr.dmi', "notfound") + legend.pixel_x = 7 * WORLD_ICON_SIZE + legend.pixel_y = 7 * WORLD_ICON_SIZE + station_map.overlays |= legend + +// TODO - Strategic Holomap support +// /datum/station_holomap/strategic/initialize_holomap(var/turf/T, var/isAI=null, var/mob/user=null) +// ..() +// station_map = image(extraMiniMaps[HOLOMAP_EXTRA_STATIONMAP_STRATEGIC]) +// legend = image('icons/effects/64x64.dmi', "strategic") +// legend.pixel_x = 3*WORLD_ICON_SIZE +// legend.pixel_y = 3*WORLD_ICON_SIZE +// station_map.overlays |= legend diff --git a/code/modules/holomap/holomap_zlevel.dm b/code/modules/holomap/holomap_zlevel.dm new file mode 100644 index 0000000000..8f76ced3d7 --- /dev/null +++ b/code/modules/holomap/holomap_zlevel.dm @@ -0,0 +1,44 @@ +// +// An enhancement to /datum/map to store more and better meta-info about Z-levels +// + +// Structure to hold zlevel info together in one nice convenient package. +// Wouldn't this be nicer than having to do those dumb arrays? +/datum/map_z_level + var/name // Friendly name of the zlevel + var/z = -1 // Actual z-index of the zlevel. This had better be right! + var/holomap_offset_x = 0 // Number of pixels to offset right (for centering) + var/holomap_offset_y = 0 // Number of pixels to offset up (for centering) + var/holomap_legend_x = 96 // x position of the holomap legend for this z + var/holomap_legend_y = 96 // y position of the holomap legend for this z + +/datum/map_z_level/New(z, name, holomap_zoom = initial(holomap_zoom), holomap_offset_x = initial(holomap_offset_x), holomap_offset_y = initial(holomap_offset_y)) + src.z = z + src.name = name + src.holomap_offset_x = holomap_offset_x + src.holomap_offset_y = holomap_offset_y + +// Map datum stuff we need +// TODO - Put this into ~map_system/maps.dm +/datum/map + var/list/zlevels = list() + +// LEGACY - This is how /vg does it, and how the code uses it. I'm in transition to use my new way (above) +// but for now lets just initialize this stuff so the code works. +/datum/map + var/list/holomap_smoosh // List of lists of zlevels to smoosh into single icons + var/list/holomap_offset_x = list() + var/list/holomap_offset_y = list() + var/list/holomap_legend_x = list() + var/list/holomap_legend_y = list() + +/datum/map/New() + ..() + // Auto-calculate any missing holomap offsets to center them, assuming they are full sized maps. + for(var/i in (holomap_offset_x.len + 1) to world.maxx) + holomap_offset_x += ((480 - world.maxx) / 2) + for(var/i in (holomap_offset_y.len + 1) to world.maxy) + holomap_offset_y += ((480 - world.maxy) / 2) + for(var/z in 1 to world.maxz) + holomap_legend_x += 96 + holomap_legend_y += 96 diff --git a/code/modules/holomap/station_holomap.dm b/code/modules/holomap/station_holomap.dm new file mode 100644 index 0000000000..2c2a0ad3e7 --- /dev/null +++ b/code/modules/holomap/station_holomap.dm @@ -0,0 +1,246 @@ +var/global/list/station_holomaps = list() + +/obj/machinery/station_map + name = "station holomap" + desc = "A virtual map of the surrounding station." + icon = 'icons/obj/machines/stationmap_vr.dmi' + icon_state = "station_map" + anchored = 1 + density = 0 + use_power = 1 + idle_power_usage = 10 + active_power_usage = 500 + auto_init = 0 // We handle our own special initialization needs. // TODO - Make this not ~Leshana + circuit = /obj/item/weapon/circuitboard/station_map + + // TODO - Port use_auto_lights from /vg - for now declare here + var/use_auto_lights = 1 + var/light_power_on = 1 + var/light_range_on = 2 + light_color = "#64C864" + + layer = ABOVE_WINDOW_LAYER + + var/mob/watching_mob = null + var/image/small_station_map = null + var/image/floor_markings = null + var/image/panel = null + + var/original_zLevel = 1 // zLevel on which the station map was initialized. + var/bogus = TRUE // set to 0 when you initialize the station map on a zLevel that has its own icon formatted for use by station holomaps. + var/datum/station_holomap/holomap_datum + +/obj/machinery/station_map/New() + ..() + holomap_datum = new() + original_zLevel = loc.z + station_holomaps += src + flags |= ON_BORDER // Why? It doesn't help if its not density + if(ticker && holomaps_initialized) + spawn(1) // Tragically we need to spawn this in order to give the frame construcing us time to set pixel_x/y + initialize() + +/obj/machinery/station_map/Destroy() + station_holomaps -= src + stopWatching() + holomap_datum = null + ..() + +/obj/machinery/station_map/initialize() + bogus = FALSE + var/turf/T = get_turf(src) + original_zLevel = T.z + if(!("[HOLOMAP_EXTRA_STATIONMAP]_[original_zLevel]" in extraMiniMaps)) + bogus = TRUE + holomap_datum.initialize_holomap_bogus() + update_icon() + return + + holomap_datum.initialize_holomap(T, reinit = TRUE) + + small_station_map = image(extraMiniMaps["[HOLOMAP_EXTRA_STATIONMAPSMALL]_[original_zLevel]"], dir = dir) + // small_station_map.plane = LIGHTING_PLANE // Not until we do planes ~Leshana + // small_station_map.layer = LIGHTING_LAYER+1 // Weird things will happen! + + floor_markings = image('icons/obj/machines/stationmap_vr.dmi', "decal_station_map") + floor_markings.dir = src.dir + // floor_markings.plane = ABOVE_TURF_PLANE // Not until we do planes ~Leshana + // floor_markings.layer = DECAL_LAYER + update_icon() + +/obj/machinery/station_map/attack_hand(var/mob/user) + if(watching_mob && (watching_mob != user)) + to_chat(user, "Someone else is currently watching the holomap.") + return + if(user.loc != loc) + to_chat(user, "You need to stand in front of \the [src].") + return + startWatching(user) + +// Let people bump up against it to watch +/obj/machinery/station_map/Bumped(var/atom/movable/AM) + if(!watching_mob && isliving(AM) && AM.loc == loc) + startWatching(AM) + +// In order to actually get Bumped() we need to block movement. We're (visually) on a wall, so people +// couldn't really walk into us anyway. But in reality we are on the turf in front of the wall, so bumping +// against where we seem is actually trying to *exit* our real loc +/obj/machinery/station_map/CheckExit(atom/movable/mover as mob|obj, turf/target as turf) + // log_debug("[src] (dir=[dir]) CheckExit([mover], [target]) get_dir() = [get_dir(target, loc)]") + if(get_dir(target, loc) == dir) // Opposite of "normal" since we are visually in the next turf over + return FALSE + else + return TRUE + +/obj/machinery/station_map/proc/startWatching(var/mob/user) + // Okay, does this belong on a screen thing or what? + // One argument is that this is an "in game" object becuase its in the world. + // But I think it actually isn't. The map isn't holo projected into the whole room, (maybe strat one is!) + // But for this, the on screen object just represents you leaning in and looking at it closely. + // So it SHOULD be a screen object. + // But it is not QUITE a hud either. So I think it shouldn't go in /datum/hud + // Okay? Yeah. Lets use screen objects but manage them manually here in the item. + // That might be a mistake... I'd rather they be managed by some central hud management system. + // But the /vg code, while the screen obj is managed, its still adding and removing image, so this is + // just as good. + + // EH JUST HACK IT FOR NOW SO WE CAN SEE HOW IT LOOKS! STOP OBSESSING, ITS BEEN AN HOUR NOW! + + // TODO - This part!! ~Leshana + if(isliving(user) && anchored && !(stat & (NOPOWER|BROKEN))) + if(user.client) + holomap_datum.station_map.loc = global_hud.holomap // Put the image on the holomap hud + holomap_datum.station_map.alpha = 0 // Set to transparent so we can fade in + animate(holomap_datum.station_map, alpha = 255, time = 5, easing = LINEAR_EASING) + flick("station_map_activate", src) + // Wait, if wea re not modifying the holomap_obj... can't it be part of the global hud? + user.client.screen |= global_hud.holomap // TODO - HACK! This should be there permenently really. + user.client.images |= holomap_datum.station_map + + watching_mob = user + moved_event.register(watching_mob, src, /obj/machinery/station_map/proc/checkPosition) + dir_set_event.register(watching_mob, src, /obj/machinery/station_map/proc/checkPosition) + destroyed_event.register(watching_mob, src, /obj/machinery/station_map/proc/stopWatching) + update_use_power(2) + + if(bogus) + to_chat(user, "The holomap failed to initialize. This area of space cannot be mapped.") + else + to_chat(user, "A hologram of the station appears before your eyes.") + +/obj/machinery/station_map/attack_ai(var/mob/living/silicon/robot/user) + return // TODO - Implement for AI ~Leshana + // user.station_holomap.toggleHolomap(user, isAI(user)) + +/obj/machinery/station_map/process() + if((stat & (NOPOWER|BROKEN)) || !anchored) + stopWatching() + +/obj/machinery/station_map/proc/checkPosition() + if(!watching_mob || (watching_mob.loc != loc) || (dir != watching_mob.dir)) + stopWatching() + +/obj/machinery/station_map/proc/stopWatching() + if(watching_mob) + if(watching_mob.client) + animate(holomap_datum.station_map, alpha = 0, time = 5, easing = LINEAR_EASING) + var/mob/M = watching_mob + spawn(5) //we give it time to fade out + M.client.images -= holomap_datum.station_map + moved_event.unregister(watching_mob, src) + dir_set_event.unregister(watching_mob, src) + destroyed_event.unregister(watching_mob, src) + watching_mob = null + update_use_power(1) + +/obj/machinery/station_map/power_change() + . = ..() + update_icon() + // TODO - Port use_auto_lights from /vg - For now implement it manually here + if(stat & NOPOWER) + set_light(0) + else + set_light(light_range_on, light_power_on) + +/obj/machinery/station_map/proc/set_broken() + stat |= BROKEN + update_icon() + +/obj/machinery/station_map/update_icon() + overlays.Cut() + if(stat & BROKEN) + icon_state = "station_mapb" + else if((stat & NOPOWER) || !anchored) + icon_state = "station_map0" + else + icon_state = "station_map" + + if(bogus) + holomap_datum.initialize_holomap_bogus() + else + small_station_map.icon = extraMiniMaps["[HOLOMAP_EXTRA_STATIONMAPSMALL]_[original_zLevel]"] + overlays |= small_station_map + holomap_datum.initialize_holomap(get_turf(src)) + + // Put the little "map" overlay down where it looks nice + if(floor_markings) + floor_markings.dir = src.dir + floor_markings.pixel_x = -src.pixel_x + floor_markings.pixel_y = -src.pixel_y + overlays += floor_markings + + if(panel_open) + overlays += "station_map-panel" + else + overlays -= "station_map-panel" + +/obj/machinery/station_map/attackby(obj/item/weapon/W as obj, mob/user as mob) + src.add_fingerprint(user) + if(default_deconstruction_screwdriver(user, W)) + return + if(default_deconstruction_crowbar(user, W)) + return + return ..() + +/obj/machinery/station_map/ex_act(severity) + switch(severity) + if(1) + qdel(src) + if(2) + if (prob(50)) + qdel(src) + else + set_broken() + if(3) + if (prob(25)) + set_broken() + +/datum/frame/frame_types/station_map + name = "Station Map Frame" + frame_class = "display" + frame_size = 3 + frame_style = "wall" + x_offset = WORLD_ICON_SIZE + y_offset = WORLD_ICON_SIZE + circuit = /obj/item/weapon/circuitboard/station_map + icon_override = 'icons/obj/machines/stationmap_vr.dmi' + +/datum/frame/frame_types/station_map/get_icon_state(var/state) + return "station_map_frame_[state]" + +/obj/structure/frame + layer = ABOVE_WINDOW_LAYER + +/obj/item/weapon/circuitboard/station_map + name = T_BOARD("Station Map") + board_type = new /datum/frame/frame_types/station_map + build_path = /obj/machinery/station_map + origin_tech = list(TECH_DATA = 3, TECH_ENGINEERING = 2) + req_components = list() + +// TODO +// //Portable holomaps, currently AI/Borg/MoMMI only + +// TODO +// OHHHH YEAH - STRATEGIC HOLOMAP! NICE! +// It will need to wait until later tho. diff --git a/icons/480x480_vr.dmi b/icons/480x480_vr.dmi new file mode 100644 index 0000000000..d175026af1 Binary files /dev/null and b/icons/480x480_vr.dmi differ diff --git a/icons/effects/64x64_vr.dmi b/icons/effects/64x64_vr.dmi new file mode 100644 index 0000000000..d03f1d9d19 Binary files /dev/null and b/icons/effects/64x64_vr.dmi differ diff --git a/icons/holomap_markers_vr.dmi b/icons/holomap_markers_vr.dmi new file mode 100644 index 0000000000..3ea32c120d Binary files /dev/null and b/icons/holomap_markers_vr.dmi differ diff --git a/icons/obj/machines/stationmap_vr.dmi b/icons/obj/machines/stationmap_vr.dmi new file mode 100644 index 0000000000..f57bf08913 Binary files /dev/null and b/icons/obj/machines/stationmap_vr.dmi differ diff --git a/maps/tether/tether_defines.dm b/maps/tether/tether_defines.dm index 1730749616..4c2db5cbf8 100644 --- a/maps/tether/tether_defines.dm +++ b/maps/tether/tether_defines.dm @@ -144,3 +144,27 @@ new /datum/random_map/noise/ore(null, 1, 1, Z_LEVEL_SOLARS, 64, 64) // Create the mining ore distribution map. return 1 + +// TODO - Re-Implement this using the /datum/map_z_level +/datum/map/tether/New() + ..() + holomap_offset_y[1] = 60 + holomap_offset_y[2] = 180 + holomap_offset_y[3] = 300 + + holomap_offset_x[1] = 100 + holomap_offset_x[2] = 100 + holomap_offset_x[3] = 100 + + holomap_offset_x[5] = 260 + holomap_offset_x[7] = 260 + holomap_offset_x[6] = 260 + + holomap_offset_y[5] = 60 + holomap_offset_y[6] = 180 + holomap_offset_y[7] = 300 + + for(var/z in list(1,2,3,5,6,7)) + holomap_legend_x[z] = 220 + holomap_legend_y[z] = 160 + holomap_smoosh = list(list(1,2,3,5,6,7)) diff --git a/vorestation.dme b/vorestation.dme index 9fabe82736..97771540fc 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -29,6 +29,7 @@ #include "code\__defines\damage_organs.dm" #include "code\__defines\dna.dm" #include "code\__defines\gamemode.dm" +#include "code\__defines\holomap.dm" #include "code\__defines\inventory_sizes.dm" #include "code\__defines\items_clothing.dm" #include "code\__defines\lighting.dm" @@ -1510,6 +1511,11 @@ #include "code\modules\holodeck\HolodeckControl.dm" #include "code\modules\holodeck\HolodeckObjects.dm" #include "code\modules\holodeck\HolodeckPrograms.dm" +#include "code\modules\holomap\generate_holomap.dm" +#include "code\modules\holomap\holomap_area.dm" +#include "code\modules\holomap\holomap_datum.dm" +#include "code\modules\holomap\holomap_zlevel.dm" +#include "code\modules\holomap\station_holomap.dm" #include "code\modules\hydroponics\_hydro_setup.dm" #include "code\modules\hydroponics\grown.dm" #include "code\modules\hydroponics\grown_inedible.dm"