From cd20465d3804d67d5a84ffad1cb87e2bccc3cd9d Mon Sep 17 00:00:00 2001 From: Woodratt Date: Thu, 2 Aug 2018 15:52:56 -0700 Subject: [PATCH] Holomap Port - Port of Holomaps from Virgo --- code/__defines/_planes+layers.dm | 9 +- code/__defines/holomap.dm | 52 ++++ code/__defines/subsystems.dm | 3 +- code/_onclick/hud/hud.dm | 16 +- code/controllers/subsystems/holomaps.dm | 24 ++ code/modules/holomap/generate_holomap.dm | 177 ++++++++++++ code/modules/holomap/holomap_area.dm | 80 ++++++ code/modules/holomap/holomap_datum.dm | 40 +++ code/modules/holomap/station_holomap.dm | 251 ++++++++++++++++++ icons/480x480.dmi | Bin 2074 -> 46289 bytes icons/effects/64x64.dmi | Bin 0 -> 6954 bytes icons/holomap_markers.dmi | Bin 0 -> 9371 bytes icons/obj/machines/stationmap.dmi | Bin 0 -> 3988 bytes maps/southern_cross/southern_cross-1.dmm | 31 ++- maps/southern_cross/southern_cross_areas.dm | 11 + maps/southern_cross/southern_cross_defines.dm | 19 ++ maps/~map_system/maps.dm | 23 ++ polaris.dme | 6 + 18 files changed, 723 insertions(+), 19 deletions(-) create mode 100644 code/__defines/holomap.dm create mode 100644 code/controllers/subsystems/holomaps.dm create mode 100644 code/modules/holomap/generate_holomap.dm create mode 100644 code/modules/holomap/holomap_area.dm create mode 100644 code/modules/holomap/holomap_datum.dm create mode 100644 code/modules/holomap/station_holomap.dm create mode 100644 icons/effects/64x64.dmi create mode 100644 icons/holomap_markers.dmi create mode 100644 icons/obj/machines/stationmap.dmi diff --git a/code/__defines/_planes+layers.dm b/code/__defines/_planes+layers.dm index 3686518108..4d258cd91f 100644 --- a/code/__defines/_planes+layers.dm +++ b/code/__defines/_planes+layers.dm @@ -73,8 +73,9 @@ What is the naming convention for planes or layers? #define ABOVE_JUNK_LAYER 3.1 // Things that want to be slightly above common objects #define DOOR_CLOSED_LAYER 3.1 // Doors when closed #define WINDOW_LAYER 3.2 // Windows + #define ABOVE_WINDOW_LAYER 3.25 //Above full tile windows so wall items are clickable #define ON_WINDOW_LAYER 3.3 // Ontop of a window - + // Mob planes #define MOB_PLANE -25 #define BELOW_MOB_LAYER 3.9 // Should be converted to plane swaps @@ -90,11 +91,11 @@ What is the naming convention for planes or layers? //#define AREA_LAYER 1 //For easy recordkeeping; this is a byond define //#define TURF_LAYER 2 //For easy recordkeeping; this is a byond define - + //#define OBJ_LAYER 3 //For easy recordkeeping; this is a byond define - + //#define MOB_LAYER 4 //For easy recordkeeping; this is a byond define - + //#define FLY_LAYER 5 //For easy recordkeeping; this is a byond define #define HUD_LAYER 20 // Above lighting, but below obfuscation. For in-game HUD effects (whereas SCREEN_LAYER is for abstract/OOC things like inventory slots) diff --git a/code/__defines/holomap.dm b/code/__defines/holomap.dm new file mode 100644 index 0000000000..0b93e03ae0 --- /dev/null +++ b/code/__defines/holomap.dm @@ -0,0 +1,52 @@ +// +// 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.dmi' // Icon file to start with when drawing holomaps (to get a 480x480 canvas). +#define HOLOMAP_ICON_SIZE 480 // Pixel width & height of the holomap icon. Used for auto-centering etc. +#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" + +#define LIST_NUMERIC_SET(L, I, V) if(!L) { L = list(); } if (L.len < I) { L.len = I; } L[I] = V + +// 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/__defines/subsystems.dm b/code/__defines/subsystems.dm index 44137b0431..c76bb80440 100644 --- a/code/__defines/subsystems.dm +++ b/code/__defines/subsystems.dm @@ -31,9 +31,10 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G #define INIT_ORDER_LIGHTING 0 #define INIT_ORDER_AIR -1 #define INIT_ORDER_PLANETS -4 +#define INIT_ORDER_HOLOMAPS -5 #define INIT_ORDER_OVERLAY -6 #define INIT_ORDER_XENOARCH -20 - + // Subsystem fire priority, from lowest to highest priority // If the subsystem isn't listed here it's either DEFAULT or PROCESS (if it's a processing subsystem child) diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm index c63519c40f..b5a4e68d6f 100644 --- a/code/_onclick/hud/hud.dm +++ b/code/_onclick/hud/hud.dm @@ -14,7 +14,8 @@ var/list/global_huds = list( global_hud.thermal, global_hud.meson, global_hud.science, - global_hud.material + global_hud.material, + global_hud.holomap ) /datum/hud/var/obj/screen/grab_intent @@ -35,6 +36,7 @@ var/list/global_huds = list( var/obj/screen/meson var/obj/screen/science var/obj/screen/material + var/obj/screen/holomap /datum/global_hud/proc/setup_overlay(var/icon_state) var/obj/screen/screen = new /obj/screen() @@ -84,6 +86,18 @@ var/list/global_huds = list( science = setup_overlay("science_hud") material = setup_overlay("material_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/controllers/subsystems/holomaps.dm b/code/controllers/subsystems/holomaps.dm new file mode 100644 index 0000000000..5fcca27480 --- /dev/null +++ b/code/controllers/subsystems/holomaps.dm @@ -0,0 +1,24 @@ +// +// Holo-Minimaps Generation Subsystem handles initialization of the holo minimaps. +// Look in code/modules/holomap/generate_holomap.dm to find generateHoloMinimaps() +// +SUBSYSTEM_DEF(holomaps) + name = "HoloMiniMaps" + init_order = INIT_ORDER_HOLOMAPS + flags = SS_NO_FIRE + var/static/holomaps_initialized = FALSE + var/static/list/holoMiniMaps = list() + var/static/list/extraMiniMaps = list() + var/static/list/station_holomaps = list() + +/datum/controller/subsystem/holomaps/Recover() + flags |= SS_NO_INIT // Make extra sure we don't initialize twice. + +/datum/controller/subsystem/holomaps/Initialize(timeofday) + generateHoloMinimaps() + . = ..() + +/datum/controller/subsystem/holomaps/stat_entry(msg) + if (!Debug2) + return // Only show up in stat panel if debugging is enabled. + . = ..() diff --git a/code/modules/holomap/generate_holomap.dm b/code/modules/holomap/generate_holomap.dm new file mode 100644 index 0000000000..e4917e0ba0 --- /dev/null +++ b/code/modules/holomap/generate_holomap.dm @@ -0,0 +1,177 @@ +// +// 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 + +// 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)) + +/// Generates all the holo minimaps, initializing it all nicely, probably. +/datum/controller/subsystem/holomaps/proc/generateHoloMinimaps() + var/start_time = world.timeofday + // Build the base map for each z level + for (var/z = 1 to world.maxz) + holoMiniMaps |= z // hack, todo fix + 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) + + 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.setup_holomap() + +// Generates the "base" holomap for one z-level, showing only the physical structure of walls and paths. +/datum/controller/subsystem/holomaps/proc/generateHoloMinimap(var/zLevel = 1) + // 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 + CHECK_TICK + 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. +/datum/controller/subsystem/holomaps/proc/generateStationMinimap(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) + + // 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! +/datum/controller/subsystem/holomaps/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 + +// 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..2cc755dfa5 --- /dev/null +++ b/code/modules/holomap/holomap_area.dm @@ -0,0 +1,80 @@ +/* +** 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/engineering/atmos/intake + holomap_color = null +/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..af4cc6f274 --- /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(SSholomaps.extraMiniMaps["[HOLOMAP_EXTRA_STATIONMAP]_[T.z]"]) + if(!cursor || reinit) + cursor = image('icons/holomap_markers.dmi', "you") + if(!legend || reinit) + legend = image('icons/effects/64x64.dmi', "legend_sc") + + 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.dmi', "stationmap") + legend = image('icons/effects/64x64.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(SSholomaps.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/station_holomap.dm b/code/modules/holomap/station_holomap.dm new file mode 100644 index 0000000000..9de56229da --- /dev/null +++ b/code/modules/holomap/station_holomap.dm @@ -0,0 +1,251 @@ +// +// Wall mounted holomap of the station +// +/obj/machinery/station_map + name = "station holomap" + desc = "A virtual map of the surrounding station." + icon = 'icons/obj/machines/stationmap.dmi' + icon_state = "station_map" + anchored = 1 + density = 0 + use_power = 1 + idle_power_usage = 10 + active_power_usage = 500 + 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" + + plane = TURF_PLANE + layer = ABOVE_TURF_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 + SSholomaps.station_holomaps += src + flags |= ON_BORDER // Why? It doesn't help if its not density + +/obj/machinery/station_map/initialize() + . = ..() + if(SSholomaps.holomaps_initialized) + spawn(1) // Tragically we need to spawn this in order to give the frame construcing us time to set pixel_x/y + setup_holomap() + +/obj/machinery/station_map/Destroy() + SSholomaps.station_holomaps -= src + stopWatching() + holomap_datum = null + . = ..() + +/obj/machinery/station_map/proc/setup_holomap() + . = ..() + bogus = FALSE + var/turf/T = get_turf(src) + original_zLevel = T.z + if(!("[HOLOMAP_EXTRA_STATIONMAP]_[original_zLevel]" in SSholomaps.extraMiniMaps)) + bogus = TRUE + holomap_datum.initialize_holomap_bogus() + update_icon() + return + + holomap_datum.initialize_holomap(T, reinit = TRUE) + + small_station_map = image(SSholomaps.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.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 = SSholomaps.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.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.dmi b/icons/480x480.dmi index 90ea9fbd55cbef9fa3da246b5092b86ccca22ec1..0b6d072855ac702f84d96e8204461feb432fac8d 100644 GIT binary patch literal 46289 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 literal 2074 zcmeAS@N?(olHy`uVBq!ia0y~yV0-|=9Be?5+AI5}0;!^^kcbkO)Z*l#%z~24{5%GR ziaEN+_wqRyh_GGQ`CW7025zUMmr9~94_I?dFZ(e0TibQ>4Ra?idRt|Eh-X?J-^Kat zCaZMRzy5HQFq=7}>w3S7y=-Y4zA)Xb zk-liTnEw?61ADTki(^Q|oVQmE84oB395}GN>*M~0?z9Jfj@#B)Zf0lraW$Ns;XpT! z1OpQr4+A4JTSEgQv%`S~Mumg}3<3rT3>*>$3@oG4qrozo97eOjXz4IoDvs6$XqDuS Yx23H5EZ#i}ft5Xjr>mdKI;Vst0NeF~X#fBK diff --git a/icons/effects/64x64.dmi b/icons/effects/64x64.dmi new file mode 100644 index 0000000000000000000000000000000000000000..79eabaac4f3a624675b62ee46d0b47360c548b70 GIT binary patch literal 6954 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 literal 0 HcmV?d00001 diff --git a/icons/obj/machines/stationmap.dmi b/icons/obj/machines/stationmap.dmi new file mode 100644 index 0000000000000000000000000000000000000000..f57bf08913e7599511193a02e37f3484868961f7 GIT binary patch literal 3988 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 dt4Y`)XSh(H?$