diff --git a/code/__DEFINES/maps.dm b/code/__DEFINES/maps.dm index cdd2739b3cf..b7043d01ff0 100644 --- a/code/__DEFINES/maps.dm +++ b/code/__DEFINES/maps.dm @@ -21,7 +21,7 @@ Last space-z level = empty #define CITY_OF_COGS "City of Cogs" #define EMPTY_AREA_1 "Empty Area 1" #define EMPTY_AREA_2 "Empty Area 2" -#define MINING "Mining Asteroid" +#define MINING_ASTEROID "Mining Asteroid" #define EMPTY_AREA_3 "Empty Area 3" #define EMPTY_AREA_4 "Empty Area 4" #define EMPTY_AREA_5 "Empty Area 5" @@ -36,11 +36,8 @@ Last space-z level = empty #define MAP_REMOVE_JOB(jobpath) /datum/job/##jobpath/map_check() { return (SSmapping.config.map_name != JOB_MODIFICATION_MAP_NAME) && ..() } //zlevel defines, can be overridden for different maps in the appropriate _maps file. -#define ZLEVEL_CENTCOM 1 #define ZLEVEL_STATION_PRIMARY 2 -#define ZLEVEL_MINING 5 #define ZLEVEL_LAVALAND 5 -#define ZLEVEL_CITYOFCOGS 6 #define ZLEVEL_EMPTY_SPACE 12 //Unless you modify it in map config should be equal to ZLEVEL_SPACEMAX #define ZLEVEL_TRANSIT 13 @@ -49,3 +46,31 @@ Last space-z level = empty #define ZLEVEL_SPACEMAX 13 #define SPACERUIN_MAP_EDGE_PAD 15 +#define ZLEVEL_SPACE_RUIN_COUNT 5 + +// traits +#define ZTRAIT_CENTCOM "CentCom" +#define ZTRAIT_STATION "Station" +#define ZTRAIT_MINING "Mining" +#define ZTRAIT_REEBE "Reebe" +#define ZTRAIT_TRANSIT "Transit" +#define ZTRAIT_AWAY "Away Mission" +#define ZTRAIT_SPACE_RUINS "Space Ruins" +#define ZTRAIT_LAVA_RUINS "Lava Ruins" +#define ZTRAIT_BOMBCAP_MULTIPLIER "Bombcap Multiplier" + +// trait definitions +#define DL_NAME "name" +#define DL_LINKAGE "linkage" +#define DL_TRAITS "traits" + +#define DECLARE_LEVEL(NAME, LINKAGE, TRAITS) list(DL_NAME = NAME, DL_LINKAGE = LINKAGE, DL_TRAITS = TRAITS) +// corresponds to basemap.dm +#define DEFAULT_MAP_TRAITS list(\ + DECLARE_LEVEL("CentCom", SELFLOOPING, list(ZTRAIT_CENTCOM = TRUE)),\ + DECLARE_LEVEL("Main Station", CROSSLINKED, list(ZTRAIT_STATION = TRUE)),\ + DECLARE_LEVEL("Empty Area 1", CROSSLINKED, list(ZTRAIT_SPACE_RUINS = TRUE)),\ + DECLARE_LEVEL("Empty Area 2", CROSSLINKED, list(ZTRAIT_SPACE_RUINS = TRUE)),\ + DECLARE_LEVEL("Lavaland", UNAFFECTED, list(ZTRAIT_MINING = TRUE, ZTRAIT_LAVA_RUINS = TRUE, ZTRAIT_BOMBCAP_MULTIPLIER = 3)),\ + DECLARE_LEVEL("Reebe", UNAFFECTED, list(ZTRAIT_REEBE = TRUE, ZTRAIT_BOMBCAP_MULTIPLIER = 0.5)),\ +) diff --git a/code/__HELPERS/level_traits.dm b/code/__HELPERS/level_traits.dm index e2a74cf8e01..4d20c9b513b 100644 --- a/code/__HELPERS/level_traits.dm +++ b/code/__HELPERS/level_traits.dm @@ -1,17 +1,17 @@ // Helpers for checking whether a z-level conforms to a specific requirement // Basic levels -#define is_centcom_level(z) ((z) == ZLEVEL_CENTCOM) +#define is_centcom_level(z) SSmapping.level_trait(z, ZTRAIT_CENTCOM) -#define is_station_level(z) ((z) in GLOB.station_z_levels) +#define is_station_level(z) SSmapping.level_trait(z, ZTRAIT_STATION) -#define is_mining_level(z) ((z) == ZLEVEL_MINING) +#define is_mining_level(z) SSmapping.level_trait(z, ZTRAIT_MINING) -#define is_reebe(z) ((z) == ZLEVEL_CITYOFCOGS) +#define is_reebe(z) SSmapping.level_trait(z, ZTRAIT_REEBE) -#define is_transit_level(z) ((z) == ZLEVEL_TRANSIT) +#define is_transit_level(z) SSmapping.level_trait(z, ZTRAIT_TRANSIT) -#define is_away_level(z) ((z) > ZLEVEL_SPACEMAX) +#define is_away_level(z) SSmapping.level_trait(z, ZTRAIT_AWAY) // If true, the singularity cannot strip away asteroid turf on this Z #define is_planet_level(z) (GLOB.z_is_planet["z"]) diff --git a/code/_globalvars/lists/mapping.dm b/code/_globalvars/lists/mapping.dm index 51af2b3525a..0d8965d10a7 100644 --- a/code/_globalvars/lists/mapping.dm +++ b/code/_globalvars/lists/mapping.dm @@ -1,14 +1,7 @@ -#define Z_NORTH 1 -#define Z_EAST 2 -#define Z_SOUTH 3 -#define Z_WEST 4 - GLOBAL_LIST_INIT(cardinals, list(NORTH, SOUTH, EAST, WEST)) GLOBAL_LIST_INIT(alldirs, list(NORTH, SOUTH, EAST, WEST, NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST)) GLOBAL_LIST_INIT(diagonals, list(NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST)) -GLOBAL_LIST_INIT(station_z_levels, list(ZLEVEL_STATION_PRIMARY)) - GLOBAL_LIST(global_map) //list/global_map = list(list(1,5),list(4,3))//an array of map Z levels. //Resulting sector map looks like diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm index d13d340b036..8046dab41e3 100644 --- a/code/controllers/subsystem/mapping.dm +++ b/code/controllers/subsystem/mapping.dm @@ -22,6 +22,9 @@ SUBSYSTEM_DEF(mapping) var/loading_ruins = FALSE + // Z-manager stuff + var/list/z_list + /datum/controller/subsystem/mapping/PreInit() if(!config) #ifdef FORCE_MAP @@ -39,28 +42,34 @@ SUBSYSTEM_DEF(mapping) repopulate_sorted_areas() process_teleport_locs() //Sets up the wizard teleport locations preloadTemplates() + + // Create space levels + for(var/I in 1 to ZLEVEL_SPACE_RUIN_COUNT) + add_new_zlevel("Empty Area [2 + I]", CROSSLINKED, list(ZTRAIT_SPACE_RUINS = TRUE)) + add_new_zlevel("Empty Area [3 + ZLEVEL_SPACE_RUIN_COUNT]", CROSSLINKED, list()) // no ruins + add_new_zlevel("Transit", UNAFFECTED, list(ZTRAIT_TRANSIT = TRUE)) + // Pick a random away mission. createRandomZlevel() - // Generate mining. + if (z_list.len < world.maxz) + add_new_zlevel("Away Mission", UNAFFECTED, list(ZTRAIT_AWAY = TRUE)) + + // Generate mining ruins loading_ruins = TRUE - var/mining_type = config.minetype - if (mining_type == "lavaland") - seedRuins(list(ZLEVEL_LAVALAND), CONFIG_GET(number/lavaland_budget), /area/lavaland/surface/outdoors/unexplored, lava_ruins_templates) - spawn_rivers() + var/list/lava_ruins = levels_by_trait(ZTRAIT_LAVA_RUINS) + if (lava_ruins.len) + seedRuins(lava_ruins, CONFIG_GET(number/lavaland_budget), /area/lavaland/surface/outdoors/unexplored, lava_ruins_templates) + for (var/lava_z in lava_ruins) + spawn_rivers(lava_z) - // deep space ruins - var/space_zlevels = list() - for(var/i in ZLEVEL_SPACEMIN to ZLEVEL_SPACEMAX) - switch(i) - if(ZLEVEL_MINING, ZLEVEL_LAVALAND, ZLEVEL_EMPTY_SPACE, ZLEVEL_TRANSIT, ZLEVEL_CITYOFCOGS) - continue - else - space_zlevels += i - - seedRuins(space_zlevels, CONFIG_GET(number/space_budget), /area/space, space_ruins_templates) + // Generate deep space ruins + var/list/space_ruins = levels_by_trait(ZTRAIT_SPACE_RUINS) + if (space_ruins.len) + seedRuins(space_ruins, CONFIG_GET(number/space_budget), /area/space, space_ruins_templates) loading_ruins = FALSE + repopulate_sorted_areas() - // Set up Z-level transistions. + // Set up Z-level transitions. setup_map_transitions() generate_station_area_list() ..() @@ -98,6 +107,8 @@ SUBSYSTEM_DEF(mapping) config = SSmapping.config next_map_config = SSmapping.next_map_config + z_list = SSmapping.z_list + /datum/controller/subsystem/mapping/proc/TryLoadZ(filename, errorList, forceLevel, last) var/static/dmm_suite/loader if(!loader) @@ -107,11 +118,6 @@ SUBSYSTEM_DEF(mapping) if(last) QDEL_NULL(loader) -/datum/controller/subsystem/mapping/proc/CreateSpace(MaxZLevel) - while(world.maxz < MaxZLevel) - ++world.maxz - CHECK_TICK - #define INIT_ANNOUNCE(X) to_chat(world, "[X]"); log_world(X) /datum/controller/subsystem/mapping/proc/loadWorld() //if any of these fail, something has gone horribly, HORRIBLY, wrong @@ -121,6 +127,7 @@ SUBSYSTEM_DEF(mapping) INIT_ANNOUNCE("Loading [config.map_name]...") TryLoadZ(config.GetFullMapPath(), FailedZs, ZLEVEL_STATION_PRIMARY) + InitializeDefaultZLevels() INIT_ANNOUNCE("Loaded station in [(REALTIMEOFDAY - start_time)/10]s!") if(SSdbcore.Connect()) var/datum/DBQuery/query_round_map_name = SSdbcore.NewQuery("UPDATE [format_table_name("round")] SET map_name = '[config.map_name]' WHERE id = [GLOB.round_id]") @@ -129,8 +136,6 @@ SUBSYSTEM_DEF(mapping) if(config.minetype != "lavaland") INIT_ANNOUNCE("WARNING: A map without lavaland set as its minetype was loaded! This is being ignored! Update the maploader code!") - CreateSpace(ZLEVEL_SPACEMAX) - if(LAZYLEN(FailedZs)) //but seriously, unless the server's filesystem is messed up this will never happen var/msg = "RED ALERT! The following map files failed to load: [FailedZs[1]]" if(FailedZs.len > 1) diff --git a/code/controllers/subsystem/minimap.dm b/code/controllers/subsystem/minimap.dm index 4bead36bb12..fa9821b85b1 100644 --- a/code/controllers/subsystem/minimap.dm +++ b/code/controllers/subsystem/minimap.dm @@ -5,9 +5,10 @@ SUBSYSTEM_DEF(minimap) var/const/MINIMAP_SIZE = 2048 var/const/TILE_SIZE = 8 - var/list/z_levels = list(ZLEVEL_STATION_PRIMARY) + var/list/z_levels /datum/controller/subsystem/minimap/Initialize(timeofday) + z_levels = SSmapping.levels_by_trait(ZTRAIT_STATION) var/hash = md5(SSmapping.config.GetFullMapPath()) if(CONFIG_GET(flag/generate_minimaps)) if(hash == trim(file2text(hash_path()))) diff --git a/code/controllers/subsystem/squeak.dm b/code/controllers/subsystem/squeak.dm index 022b659d8a2..861bb0d8d5a 100644 --- a/code/controllers/subsystem/squeak.dm +++ b/code/controllers/subsystem/squeak.dm @@ -34,7 +34,7 @@ SUBSYSTEM_DEF(squeak) /datum/controller/subsystem/squeak/proc/find_exposed_wires() exposed_wires.Cut() var/list/all_turfs - for (var/z in GLOB.station_z_levels) + for (var/z in SSmapping.levels_by_trait(ZTRAIT_STATION)) all_turfs += block(locate(1,1,z), locate(world.maxx,world.maxy,z)) for(var/turf/open/floor/plating/T in all_turfs) if(is_blocked_turf(T)) diff --git a/code/datums/explosion.dm b/code/datums/explosion.dm index 9b5cd18774f..0616d0e4c67 100644 --- a/code/datums/explosion.dm +++ b/code/datums/explosion.dm @@ -1,6 +1,4 @@ #define EXPLOSION_THROW_SPEED 4 -#define CITYOFCOGS_CAP_MULTIPLIER 0.5 -#define MINING_CAP_MULTIPLIER 3 GLOBAL_LIST_EMPTY(explosions) //Against my better judgement, I will return the explosion datum @@ -54,17 +52,14 @@ GLOBAL_LIST_EMPTY(explosions) var/orig_dev_range = devastation_range var/orig_heavy_range = heavy_impact_range var/orig_light_range = light_impact_range - + var/orig_max_distance = max(devastation_range, heavy_impact_range, light_impact_range, flash_range, flame_range) - + //Zlevel specific bomb cap multiplier - var/cap_multiplier = 1 - switch(epicenter.z) - if(ZLEVEL_CITYOFCOGS) - cap_multiplier = CITYOFCOGS_CAP_MULTIPLIER - if(ZLEVEL_MINING) - cap_multiplier = MINING_CAP_MULTIPLIER - + var/cap_multiplier = SSmapping.level_trait(epicenter.z, ZTRAIT_BOMBCAP_MULTIPLIER) + if (isnull(cap_multiplier)) + cap_multiplier = 1 + if(!ignorecap) devastation_range = min(GLOB.MAX_EX_DEVESTATION_RANGE * cap_multiplier, devastation_range) heavy_impact_range = min(GLOB.MAX_EX_HEAVY_RANGE * cap_multiplier, heavy_impact_range) @@ -91,11 +86,11 @@ GLOBAL_LIST_EMPTY(explosions) if(adminlog) message_admins("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range], [flame_range]) in area: [epi_area] [ADMIN_COORDJMP(epicenter)]") log_game("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range], [flame_range]) in area [epicenter.loc.name] ([epicenter.x],[epicenter.y],[epicenter.z])") - + var/x0 = epicenter.x var/y0 = epicenter.y var/z0 = epicenter.z - + SSblackbox.record_feedback("associative", "explosion", 1, list("dev" = devastation_range, "heavy" = heavy_impact_range, "light" = light_impact_range, "flash" = flash_range, "flame" = flame_range, "orig_dev" = orig_dev_range, "orig_heavy" = orig_heavy_range, "orig_light" = orig_light_range, "x" = x0, "y" = y0, "z" = z0, "area" = epi_area.type)) // Play sounds; we want sounds to be different depending on distance so we will manually do it ourselves. @@ -199,7 +194,7 @@ GLOBAL_LIST_EMPTY(explosions) //------- EX_ACT AND TURF FIRES ------- if(T == epicenter) // Ensures explosives detonating from bags trigger other explosives in that bag - var/list/items = list() + var/list/items = list() for(var/I in T) var/atom/A = I items += A.GetAllContents() @@ -418,6 +413,3 @@ GLOBAL_LIST_EMPTY(explosions) // 10 explosion power is a (1, 3, 6) explosion. // 5 explosion power is a (0, 1, 3) explosion. // 1 explosion power is a (0, 0, 1) explosion. - -#undef CITYOFCOGS_CAP_MULTIPLIER -#undef MINING_CAP_MULTIPLIER diff --git a/code/datums/helper_datums/teleport.dm b/code/datums/helper_datums/teleport.dm index c030bd4c2a3..f90d6eed321 100644 --- a/code/datums/helper_datums/teleport.dm +++ b/code/datums/helper_datums/teleport.dm @@ -166,9 +166,12 @@ // Safe location finder -/proc/find_safe_turf(zlevel = ZLEVEL_STATION_PRIMARY, list/zlevels, extended_safety_checks = FALSE) +/proc/find_safe_turf(zlevel, list/zlevels, extended_safety_checks = FALSE) if(!zlevels) - zlevels = list(zlevel) + if (zlevel) + zlevels = list(zlevel) + else + zlevels = SSmapping.levels_by_trait(ZTRAIT_STATION) var/cycles = 1000 for(var/cycle in 1 to cycles) // DRUNK DIALLING WOOOOOOOOO diff --git a/code/datums/position_point_vector.dm b/code/datums/position_point_vector.dm index 635ae0bbec5..6fae092c9dd 100644 --- a/code/datums/position_point_vector.dm +++ b/code/datums/position_point_vector.dm @@ -133,7 +133,7 @@ if(y > maxy) y -= maxy move_zy += 1 - var/datum/space_level/S = GLOB.z_levels_list["[z]"] + var/datum/space_level/S = SSmapping.get_level(z) if(move_zx != 0) var/datum/space_level/L = S.neigbours["[move_zx < 0? WEST : EAST]"] z = L.z_value diff --git a/code/game/gamemodes/blob/blob_report.dm b/code/game/gamemodes/blob/blob_report.dm index 6585da0ba43..4385b732c3d 100644 --- a/code/game/gamemodes/blob/blob_report.dm +++ b/code/game/gamemodes/blob/blob_report.dm @@ -8,7 +8,7 @@ var/mach = 0 /datum/station_state/proc/count() - for(var/Z in GLOB.station_z_levels) + for(var/Z in SSmapping.levels_by_trait(ZTRAIT_STATION)) for(var/turf/T in block(locate(1,1,Z), locate(world.maxx,world.maxy,Z))) // don't count shuttles since they may have just left if(istype(T.loc, /area/shuttle)) diff --git a/code/game/gamemodes/meteor/meteors.dm b/code/game/gamemodes/meteor/meteors.dm index 9e0c9652715..13ab7a8bb12 100644 --- a/code/game/gamemodes/meteor/meteors.dm +++ b/code/game/gamemodes/meteor/meteors.dm @@ -31,7 +31,7 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event var/max_i = 10//number of tries to spawn meteor. while(!isspaceturf(pickedstart)) var/startSide = pick(GLOB.cardinals) - var/startZ = pick(GLOB.station_z_levels) + var/startZ = pick(SSmapping.levels_by_trait(ZTRAIT_STATION)) pickedstart = spaceDebrisStartLoc(startSide, startZ) pickedgoal = spaceDebrisFinishLoc(startSide, startZ) max_i-- @@ -40,7 +40,6 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event var/Me = pickweight(meteortypes) var/obj/effect/meteor/M = new Me(pickedstart, pickedgoal) M.dest = pickedgoal - M.z_original = M.z /proc/spaceDebrisStartLoc(startSide, Z) var/starty @@ -95,7 +94,7 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event pass_flags = PASSTABLE var/heavy = 0 var/meteorsound = 'sound/effects/meteorimpact.ogg' - var/z_original = ZLEVEL_STATION_PRIMARY + var/z_original var/threat = 0 // used for determining which meteors are most interesting var/lifetime = DEFAULT_METEOR_LIFETIME var/timerid = null @@ -126,6 +125,7 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event /obj/effect/meteor/Initialize(mapload, target) . = ..() + z_original = z GLOB.meteor_list += src SSaugury.register_doom(src, threat) SpinAnimation() diff --git a/code/game/machinery/computer/camera_advanced.dm b/code/game/machinery/computer/camera_advanced.dm index 7c790f63de7..f007050560c 100644 --- a/code/game/machinery/computer/camera_advanced.dm +++ b/code/game/machinery/computer/camera_advanced.dm @@ -17,7 +17,7 @@ /obj/machinery/computer/camera_advanced/Initialize() . = ..() if(station_lock_override) - z_lock = GLOB.station_z_levels.Copy() + z_lock = SSmapping.levels_by_trait(ZTRAIT_STATION) /obj/machinery/computer/camera_advanced/syndie icon_keyboard = "syndie_key" diff --git a/code/game/turfs/simulated/river.dm b/code/game/turfs/simulated/river.dm index a5753edcd13..79846791d3a 100644 --- a/code/game/turfs/simulated/river.dm +++ b/code/game/turfs/simulated/river.dm @@ -4,7 +4,7 @@ #define RANDOM_LOWER_X 50 #define RANDOM_LOWER_Y 50 -/proc/spawn_rivers(target_z = ZLEVEL_LAVALAND, nodes = 4, turf_type = /turf/open/lava/smooth/lava_land_surface, whitelist_area = /area/lavaland/surface/outdoors, min_x = RANDOM_LOWER_X, min_y = RANDOM_LOWER_Y, max_x = RANDOM_UPPER_X, max_y = RANDOM_UPPER_Y) +/proc/spawn_rivers(target_z, nodes = 4, turf_type = /turf/open/lava/smooth/lava_land_surface, whitelist_area = /area/lavaland/surface/outdoors, min_x = RANDOM_LOWER_X, min_y = RANDOM_LOWER_Y, max_x = RANDOM_UPPER_X, max_y = RANDOM_UPPER_Y) var/list/river_nodes = list() var/num_spawned = 0 while(num_spawned < nodes) diff --git a/code/modules/admin/verbs/mapping.dm b/code/modules/admin/verbs/mapping.dm index ce50378f4d9..fac7d93f9a3 100644 --- a/code/modules/admin/verbs/mapping.dm +++ b/code/modules/admin/verbs/mapping.dm @@ -45,7 +45,8 @@ GLOBAL_LIST_INIT(admin_verbs_debug_mapping, list( /client/proc/start_line_profiling, /client/proc/stop_line_profiling, /client/proc/show_line_profiling, - /client/proc/create_mapping_job_icons + /client/proc/create_mapping_job_icons, + /client/proc/debug_z_levels, )) /obj/effect/debugging/mapfix_marker @@ -292,4 +293,64 @@ GLOBAL_VAR_INIT(say_disabled, FALSE) //Also add the x for(var/x_number in 1 to 4) final.Insert(icon('icons/mob/screen_gen.dmi', "x[x_number == 1 ? "" : x_number]"), "x[x_number == 1 ? "" : x_number]") - fcopy(final, "icons/mob/landmarks.dmi") \ No newline at end of file + fcopy(final, "icons/mob/landmarks.dmi") + +/client/proc/debug_z_levels() + set name = "Debug Z-Levels" + set category = "Mapping" + + var/list/z_list = SSmapping.z_list + var/list/messages = list() + messages += "World: [world.maxx] x [world.maxy] x [world.maxz]
" + + var/list/linked_levels = list() + var/min_x = INFINITY + var/min_y = INFINITY + var/max_x = -INFINITY + var/max_y = -INFINITY + + for(var/z in 1 to max(world.maxz, z_list.len)) + if (z > z_list.len) + messages += "[z]: Unmanaged (out of bounds)
" + continue + var/datum/space_level/S = z_list[z] + if (!S) + messages += "[z]: Unmanaged (null)
" + continue + var/linkage + switch (S.linkage) + if (UNAFFECTED) + linkage = "no linkage" + if (SELFLOOPING) + linkage = "self-looping" + if (CROSSLINKED) + linkage = "linked at ([S.xi], [S.yi])" + linked_levels += S + min_x = min(min_x, S.xi) + min_y = min(min_y, S.yi) + max_x = max(max_x, S.xi) + max_y = max(max_y, S.yi) + else + linkage = "unknown linkage '[S.linkage]'" + + messages += "[z]: [S.name], [linkage], traits: [json_encode(S.traits)]
" + if (S.z_value != z) + messages += "-- z_value is [S.z_value], should be [z]
" + if (S.name == initial(S.name)) + messages += "-- name not set
" + if (z > world.maxz) + messages += "-- exceeds max z" + + var/grid[max_x - min_x + 1][max_y - min_y + 1] + for(var/datum/space_level/S in linked_levels) + grid[S.xi - min_x + 1][S.yi - min_y + 1] = S.z_value + + messages += "" + for(var/y in max_y to min_y step -1) + var/list/part = list() + for(var/x in min_x to max_x) + part += "[grid[x - min_x + 1][y - min_y + 1]]" + messages += "" + messages += "
[part.Join("")]
" + + to_chat(src, messages.Join("")) diff --git a/code/modules/awaymissions/signpost.dm b/code/modules/awaymissions/signpost.dm index f6fd4d9071f..b1f85ca5374 100644 --- a/code/modules/awaymissions/signpost.dm +++ b/code/modules/awaymissions/signpost.dm @@ -5,12 +5,12 @@ anchored = TRUE density = TRUE var/question = "Travel back?" - var/list/zlevels = list() + var/list/zlevels /obj/structure/signpost/New() . = ..() set_light(2) - zlevels = GLOB.station_z_levels + zlevels = SSmapping.levels_by_trait(ZTRAIT_STATION) /obj/structure/signpost/attackby(obj/item/W, mob/user, params) return attack_hand(user) @@ -44,6 +44,6 @@ zlevels = list() for(var/i in 1 to world.maxz) zlevels += i - zlevels -= ZLEVEL_CENTCOM // no easy victory, even with meme signposts + zlevels -= SSmapping.levels_by_trait(ZTRAIT_CENTCOM) // no easy victory, even with meme signposts // also, could you think of the horror if they ended up in a holodeck // template or something diff --git a/code/modules/events/immovable_rod.dm b/code/modules/events/immovable_rod.dm index 9612fd8018c..2bb75cfade2 100644 --- a/code/modules/events/immovable_rod.dm +++ b/code/modules/events/immovable_rod.dm @@ -32,8 +32,9 @@ In my current plan for it, 'solid' will be defined as anything with density == 1 /datum/round_event/immovable_rod/start() var/datum/round_event_control/immovable_rod/C = control var/startside = pick(GLOB.cardinals) - var/turf/startT = spaceDebrisStartLoc(startside, ZLEVEL_STATION_PRIMARY) - var/turf/endT = spaceDebrisFinishLoc(startside, ZLEVEL_STATION_PRIMARY) + var/z = pick(SSmapping.levels_by_trait(ZTRAIT_STATION)) + var/turf/startT = spaceDebrisStartLoc(startside, z) + var/turf/endT = spaceDebrisFinishLoc(startside, z) new /obj/effect/immovablerod(startT, endT, C.special_target) /obj/effect/immovablerod @@ -60,7 +61,7 @@ In my current plan for it, 'solid' will be defined as anything with density == 1 enter_link="(Click to orbit)", source=src, action=NOTIFY_ORBIT) GLOB.poi_list += src - + var/special_target_valid = FALSE if(special_target) var/turf/T = get_turf(special_target) diff --git a/code/modules/mapping/space_management/space_level.dm b/code/modules/mapping/space_management/space_level.dm new file mode 100644 index 00000000000..22a6d6ed6f1 --- /dev/null +++ b/code/modules/mapping/space_management/space_level.dm @@ -0,0 +1,14 @@ +/datum/space_level + var/name = "Your config settings failed, you need to fix this for the datum space levels to work" + var/list/neigbours = list() + var/list/traits + var/z_value = 1 //actual z placement + var/linkage = SELFLOOPING + var/xi + var/yi //imaginary placements on the grid + +/datum/space_level/New(new_z, new_name, new_linkage = SELFLOOPING, list/new_traits = list()) + z_value = new_z + name = new_name + traits = new_traits + set_linkage(new_linkage) diff --git a/code/modules/space_transition/space_transition.dm b/code/modules/mapping/space_management/space_transition.dm similarity index 75% rename from code/modules/space_transition/space_transition.dm rename to code/modules/mapping/space_management/space_transition.dm index edcad9b6204..fa7cab94366 100644 --- a/code/modules/space_transition/space_transition.dm +++ b/code/modules/mapping/space_management/space_transition.dm @@ -1,18 +1,6 @@ -//This is a simple 3 by 3 grid working off the corpse of the space torus. The donut is dead, cube has been avenged! - -GLOBAL_LIST_EMPTY(z_levels_list) - -/datum/space_level - var/name = "Your config settings failed, you need to fix this for the datum space levels to work" - var/list/neigbours = list() - var/z_value = 1 //actual z placement - var/linked = SELFLOOPING - var/xi - var/yi //imaginary placements on the grid - -/datum/space_level/New(transition_type) - linked = transition_type - if(linked == SELFLOOPING) +/datum/space_level/proc/set_linkage(new_linkage) + linkage = new_linkage + if(linkage == SELFLOOPING) neigbours = list() var/list/L = list(TEXT_NORTH,TEXT_SOUTH,TEXT_EAST,TEXT_WEST) for(var/A in L) @@ -69,21 +57,15 @@ GLOBAL_LIST_EMPTY(z_levels_list) if(y-1 >= 1) neigbours |= grid[x][y-1] -/proc/setup_map_transitions() //listamania +/datum/controller/subsystem/mapping/proc/setup_map_transitions() //listamania var/list/SLS = list() - var/datum/space_level/D - var/list/cached_transitions = SSmapping.config.transition_config - var/conf_set_len = cached_transitions.len - var/k = 1 - for(var/A in cached_transitions) - D = new(cached_transitions[A]) - D.name = A - D.z_value = k - if(D.linked != CROSSLINKED) - GLOB.z_levels_list["[D.z_value]"] = D - else + var/list/cached_z_list = z_list + var/conf_set_len = 0 + for(var/A in cached_z_list) + var/datum/space_level/D = A + if (D.linkage == CROSSLINKED) SLS.Add(D) - k++ + conf_set_len++ var/list/point_grid[conf_set_len*2+1][conf_set_len*2+1] var/list/grid = list() var/datum/space_transition_point/P @@ -99,7 +81,7 @@ GLOBAL_LIST_EMPTY(z_levels_list) var/list/used_points = list() grid.Cut() while(SLS.len) - D = pick_n_take(SLS) + var/datum/space_level/D = pick_n_take(SLS) D.xi = P.x D.yi = P.y P.spl = D @@ -108,10 +90,7 @@ GLOBAL_LIST_EMPTY(z_levels_list) possible_points.Remove(used_points) D.set_neigbours(used_points) P = pick(possible_points) - grid["[D.z_value]"] = D - - for(var/A in GLOB.z_levels_list) - grid[A] = GLOB.z_levels_list[A] + CHECK_TICK //Lists below are pre-calculated values arranged in the list in such a way to be easily accessable in the loop by the counter //Its either this or madness with lotsa math @@ -123,13 +102,12 @@ GLOBAL_LIST_EMPTY(z_levels_list) var/list/x_pos_transition = list(1, 1, TRANSITIONEDGE + 2, world.maxx - TRANSITIONEDGE - 2) //values of x for the transition from respective blocks on the side of zlevel, 1 is being translated into turfs respective x value later in the code var/list/y_pos_transition = list(TRANSITIONEDGE + 2, world.maxy - TRANSITIONEDGE - 2, 1, 1) //values of y for the transition from respective blocks on the side of zlevel, 1 is being translated into turfs respective y value later in the code - for(var/zlevelnumber = 1, zlevelnumber<=grid.len, zlevelnumber++) - D = grid["[zlevelnumber]"] - if(!D) - CRASH("[zlevelnumber] position has no space level datum.") - if(!(D.neigbours.len)) + for(var/I in cached_z_list) + var/datum/space_level/D = I + if(!D.neigbours.len) continue - for(var/side = 1, side<5, side++) + var/zlevelnumber = D.z_value + for(var/side in 1 to 4) var/turf/beginning = locate(x_pos_beginning[side], y_pos_beginning[side], zlevelnumber) var/turf/ending = locate(x_pos_ending[side], y_pos_ending[side], zlevelnumber) var/list/turfblock = block(beginning, ending) @@ -143,12 +121,8 @@ GLOBAL_LIST_EMPTY(z_levels_list) while(D.neigbours["[dirside]"] && D.neigbours["[dirside]"] != D) D = D.neigbours["[dirside]"] zdestination = D.z_value - D = grid["[zlevelnumber]"] + D = I for(var/turf/open/space/S in turfblock) S.destination_x = x_pos_transition[side] == 1 ? S.x : x_pos_transition[side] S.destination_y = y_pos_transition[side] == 1 ? S.y : y_pos_transition[side] S.destination_z = zdestination - //S.maptext = "[zdestination]" // for debugging - - for(var/A in grid) - GLOB.z_levels_list[A] = grid[A] diff --git a/code/modules/mapping/space_management/traits.dm b/code/modules/mapping/space_management/traits.dm new file mode 100644 index 00000000000..78e2fa2a21e --- /dev/null +++ b/code/modules/mapping/space_management/traits.dm @@ -0,0 +1,46 @@ +// Look up levels[z].traits[trait] +/datum/controller/subsystem/mapping/proc/level_trait(z, trait) + if (!z) + return null + var/list/trait_list + if (z_list) + var/datum/space_level/S = get_level(z) + trait_list = S.traits + else + var/list/default_map_traits = DEFAULT_MAP_TRAITS + trait_list = default_map_traits[z][DL_TRAITS] + return trait_list[trait] + +// Check if levels[z] has any of the specified traits +/datum/controller/subsystem/mapping/proc/level_has_any_trait(z, list/traits) + for (var/I in traits) + if (level_trait(z, I)) + return TRUE + return FALSE + +// Check if levels[z] has all of the specified traits +/datum/controller/subsystem/mapping/proc/level_has_all_traits(z, list/traits) + for (var/I in traits) + if (!level_trait(z, I)) + return FALSE + return TRUE + +// Get a list of all z which have the specified trait +/datum/controller/subsystem/mapping/proc/levels_by_trait(trait) + . = list() + var/list/_z_list = z_list + for(var/A in _z_list) + var/datum/space_level/S = A + if (S.traits[trait]) + . += S.z_value + +// Get a list of all z which have any of the specified traits +/datum/controller/subsystem/mapping/proc/levels_by_any_trait(list/traits) + . = list() + var/list/_z_list = z_list + for(var/A in _z_list) + var/datum/space_level/S = A + for (var/trait in traits) + if (S.traits[trait]) + . += S.z_value + break diff --git a/code/modules/mapping/space_management/zlevel_manager.dm b/code/modules/mapping/space_management/zlevel_manager.dm new file mode 100644 index 00000000000..5cb7261348c --- /dev/null +++ b/code/modules/mapping/space_management/zlevel_manager.dm @@ -0,0 +1,32 @@ +// Populate the space level list and prepare space transitions +/datum/controller/subsystem/mapping/proc/InitializeDefaultZLevels() + if (z_list) // subsystem/Recover or badminnery, no need + return + + z_list = list() + var/list/default_map_traits = DEFAULT_MAP_TRAITS + + if (default_map_traits.len != world.maxz) + WARNING("More or less map attributes pre-defined ([default_map_traits.len]) than existent z-levels ([world.maxz]). Ignoring the larger.") + if (default_map_traits.len > world.maxz) + default_map_traits.Cut(world.maxz + 1) + + for (var/I in 1 to default_map_traits.len) + var/list/features = default_map_traits[I] + var/datum/space_level/S = new(I, features[DL_NAME], features[DL_LINKAGE], features[DL_TRAITS]) + z_list += S + +/datum/controller/subsystem/mapping/proc/add_new_zlevel(name, linkage = SELFLOOPING, traits = list(), z_type = /datum/space_level) + var/new_z = z_list.len + 1 + if (world.maxz < new_z) + ++world.maxz + CHECK_TICK + // TODO: sleep here if the Z level needs to be cleared + var/datum/space_level/S = new z_type(new_z, name, linkage, traits) + z_list += S + return new_z + +/datum/controller/subsystem/mapping/proc/get_level(z) + . = z_list[z] + if (!.) + CRASH("Unmanaged z-level: '[z]'") diff --git a/code/modules/mining/aux_base.dm b/code/modules/mining/aux_base.dm index df20ce5921b..5ea18b631c5 100644 --- a/code/modules/mining/aux_base.dm +++ b/code/modules/mining/aux_base.dm @@ -102,7 +102,10 @@ interface with the mining shuttle at the landing site if a mobile beacon is also if(href_list["random"] && !possible_destinations) usr.changeNext_move(CLICK_CD_RAPID) //Anti-spam - var/turf/LZ = safepick(Z_TURFS(ZLEVEL_MINING)) //Pick a random mining Z-level turf + var/list/all_mining_turfs = list() + for (var/z_level in SSmapping.levels_by_trait(ZTRAIT_MINING)) + all_mining_turfs += Z_TURFS(z_level) + var/turf/LZ = safepick(all_mining_turfs) //Pick a random mining Z-level turf if(!ismineralturf(LZ) && !istype(LZ, /turf/open/floor/plating/asteroid)) //Find a suitable mining turf. Reduces chance of landing in a bad area to_chat(usr, "Landing zone scan failed. Please try again.") diff --git a/code/modules/procedural_mapping/mapGenerators/lava_river.dm b/code/modules/procedural_mapping/mapGenerators/lava_river.dm index d825a02846b..0486acae563 100644 --- a/code/modules/procedural_mapping/mapGenerators/lava_river.dm +++ b/code/modules/procedural_mapping/mapGenerators/lava_river.dm @@ -1,6 +1,6 @@ /datum/mapGenerator/lavaland - var/start_z = ZLEVEL_LAVALAND + var/start_z var/min_x = 0 var/min_y = 0 var/max_x = 0 @@ -19,11 +19,9 @@ /datum/mapGeneratorModule/river var/river_type = /turf/open/lava/smooth var/river_nodes = 4 - var/start_z = ZLEVEL_LAVALAND /datum/mapGeneratorModule/river/generate() var/datum/mapGenerator/lavaland/L = mother if(!istype(L)) return - start_z = L.start_z - spawn_rivers(start_z, river_nodes, river_type, min_x = L.min_x, min_y = L.min_y, max_x = L.max_x, max_y = L.max_y) + spawn_rivers(L.start_z, river_nodes, river_type, min_x = L.min_x, min_y = L.min_y, max_x = L.max_x, max_y = L.max_y) diff --git a/tgstation.dme b/tgstation.dme index 73e99624d18..edbd5f5d1e7 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -1619,6 +1619,10 @@ #include "code\modules\mapping\mapping_helpers.dm" #include "code\modules\mapping\reader.dm" #include "code\modules\mapping\ruins.dm" +#include "code\modules\mapping\space_management\space_level.dm" +#include "code\modules\mapping\space_management\space_transition.dm" +#include "code\modules\mapping\space_management\traits.dm" +#include "code\modules\mapping\space_management\zlevel_manager.dm" #include "code\modules\mining\abandoned_crates.dm" #include "code\modules\mining\aux_base.dm" #include "code\modules\mining\aux_base_camera.dm" @@ -2254,7 +2258,6 @@ #include "code\modules\shuttle\supply.dm" #include "code\modules\shuttle\syndicate.dm" #include "code\modules\shuttle\white_ship.dm" -#include "code\modules\space_transition\space_transition.dm" #include "code\modules\spells\spell.dm" #include "code\modules\spells\spell_types\aimed.dm" #include "code\modules\spells\spell_types\area_teleport.dm"