From 1345beac4b991b78aa4e1e357c72772ab7018770 Mon Sep 17 00:00:00 2001 From: Fluffy <65877598+FluffyGhoster@users.noreply.github.com> Date: Mon, 22 Jul 2024 15:00:38 +0200 Subject: [PATCH] Added the z-level manager system from TG (#19532) Added the z-level manager system from TG, mostly --- aurorastation.dme | 47 +++++---- code/__DEFINES/_flags.dm | 13 +++ code/__DEFINES/directional.dm | 14 +++ code/__DEFINES/mapping.dm | 6 ++ code/__DEFINES/maps.dm | 44 +++++++++ code/__DEFINES/multiz.dm | 8 ++ code/__DEFINES/turfs.dm | 26 ----- code/_onclick/hud/screen_objects.dm | 5 +- code/controllers/subsystems/explosives.dm | 16 ++-- code/controllers/subsystems/falling.dm | 3 +- .../subsystems/initialization/atlas.dm | 43 +++++++-- code/controllers/subsystems/mapping.dm | 53 +++++++++++ code/controllers/subsystems/zcopy.dm | 2 +- code/game/atoms_movable.dm | 2 +- .../endgame/supermatter_cascade/blob.dm | 4 +- code/game/sound.dm | 4 +- .../turfs/flooring/flooring_premade_other.dm | 1 - code/game/turfs/simulated/floor_attackby.dm | 2 +- code/game/turfs/simulated/wall_attacks.dm | 3 +- code/game/turfs/space/space.dm | 2 +- code/game/turfs/turf.dm | 24 ++--- code/game/turfs/turf_changing.dm | 2 +- code/game/world.dm | 2 + code/modules/atmospherics/he_pipes.dm | 4 +- .../spacesuits/rig/modules/utility.dm | 5 +- code/modules/lighting/lighting_corner.dm | 4 +- code/modules/{maps => mapping}/dmm_suite.dm | 0 .../{maps => mapping}/helper_landmarks.dm | 0 .../modules/{maps => mapping}/map_template.dm | 31 +++++- .../planet_types/asteroid.dm | 0 .../{maps => mapping}/planet_types/barren.dm | 0 .../{maps => mapping}/planet_types/crystal.dm | 0 .../{maps => mapping}/planet_types/desert.dm | 0 .../{maps => mapping}/planet_types/grass.dm | 0 .../{maps => mapping}/planet_types/jungle.dm | 0 .../{maps => mapping}/planet_types/lava.dm | 0 .../planet_types/lore/burzsia.dm | 0 .../planet_types/lore/konyang.dm | 0 .../planet_types/lore/srandmarr.dm | 0 .../planet_types/lore/tauceti.dm | 0 .../planet_types/lore/uueoaesa.dm | 0 .../{maps => mapping}/planet_types/snow.dm | 0 code/modules/{maps => mapping}/reader.dm | 2 +- code/modules/{maps => mapping}/ruins.dm | 0 .../mapping/space_management/space_level.dm | 22 +++++ .../space_management/space_reservation.dm | 95 +++++++++++++++++++ .../space_management/space_transition.dm | 6 ++ .../mapping/space_management/traits.dm | 16 ++++ .../space_management/zlevel_manager.dm | 21 ++++ code/modules/{maps => mapping}/swapmaps.dm | 0 code/modules/mining/drilling/drill.dm | 2 +- code/modules/mining/mine_items.dm | 9 +- code/modules/mining/mine_turfs.dm | 7 +- code/modules/mob/living/carbon/human/human.dm | 7 +- .../living/carbon/human/human_attackhand.dm | 3 +- .../mob/living/carbon/human/human_movement.dm | 2 +- .../mob/living/maneuvers/maneuver_leap.dm | 4 +- .../living/silicon/robot/robot_movement.dm | 3 +- code/modules/mob/mob.dm | 4 +- code/modules/multiz/basic.dm | 39 +------- code/modules/multiz/disabled.dm | 5 - code/modules/multiz/hoist.dm | 6 +- code/modules/multiz/mobile_ladders.dm | 6 +- code/modules/multiz/movement.dm | 13 ++- code/modules/multiz/pipes.dm | 7 +- code/modules/multiz/structures.dm | 8 +- code/modules/multiz/turfs/open_space.dm | 11 ++- code/modules/multiz/zmimic/mimic_common.dm | 4 +- code/modules/multiz/zmimic/mimic_turf.dm | 2 +- code/modules/overmap/exoplanets/exoplanet.dm | 5 +- code/modules/overmap/sectors.dm | 6 +- code/modules/overmap/ships/landable.dm | 9 +- code/modules/power/cable.dm | 10 +- code/modules/power/singularity/act.dm | 8 +- code/modules/power/singularity/singularity.dm | 3 +- code/modules/power/tesla/energy_ball.dm | 6 +- code/modules/random_map/automata/caves.dm | 2 +- code/modules/recycling/disposal.dm | 6 +- code/modules/shieldgen/shield_gen.dm | 4 +- code/modules/shuttles/shuttle.dm | 10 +- code/modules/turbolift/turbolift.dm | 6 +- code/modules/vehicles/droppod.dm | 4 +- code/modules/weather/weather_debug.dm | 4 +- code/modules/weather/weather_init.dm | 2 +- code/unit_tests/create_and_destroy.dm | 3 + code/unit_tests/map_tests.dm | 32 +------ html/changelogs/fluffyghost-zlevelmanager.yml | 58 +++++++++++ maps/_common/mapsystem/map.dm | 5 +- maps/away/away_site/blueriver/blueriver.dm | 1 - maps/away/away_sites.dm | 1 - 90 files changed, 614 insertions(+), 245 deletions(-) create mode 100644 code/__DEFINES/directional.dm create mode 100644 code/__DEFINES/mapping.dm create mode 100644 code/__DEFINES/maps.dm create mode 100644 code/__DEFINES/multiz.dm rename code/modules/{maps => mapping}/dmm_suite.dm (100%) rename code/modules/{maps => mapping}/helper_landmarks.dm (100%) rename code/modules/{maps => mapping}/map_template.dm (90%) rename code/modules/{maps => mapping}/planet_types/asteroid.dm (100%) rename code/modules/{maps => mapping}/planet_types/barren.dm (100%) rename code/modules/{maps => mapping}/planet_types/crystal.dm (100%) rename code/modules/{maps => mapping}/planet_types/desert.dm (100%) rename code/modules/{maps => mapping}/planet_types/grass.dm (100%) rename code/modules/{maps => mapping}/planet_types/jungle.dm (100%) rename code/modules/{maps => mapping}/planet_types/lava.dm (100%) rename code/modules/{maps => mapping}/planet_types/lore/burzsia.dm (100%) rename code/modules/{maps => mapping}/planet_types/lore/konyang.dm (100%) rename code/modules/{maps => mapping}/planet_types/lore/srandmarr.dm (100%) rename code/modules/{maps => mapping}/planet_types/lore/tauceti.dm (100%) rename code/modules/{maps => mapping}/planet_types/lore/uueoaesa.dm (100%) rename code/modules/{maps => mapping}/planet_types/snow.dm (100%) rename code/modules/{maps => mapping}/reader.dm (99%) rename code/modules/{maps => mapping}/ruins.dm (100%) create mode 100644 code/modules/mapping/space_management/space_level.dm create mode 100644 code/modules/mapping/space_management/space_reservation.dm create mode 100644 code/modules/mapping/space_management/space_transition.dm create mode 100644 code/modules/mapping/space_management/traits.dm create mode 100644 code/modules/mapping/space_management/zlevel_manager.dm rename code/modules/{maps => mapping}/swapmaps.dm (100%) create mode 100644 html/changelogs/fluffyghost-zlevelmanager.yml diff --git a/aurorastation.dme b/aurorastation.dme index dddbafc82db..5ff542210f7 100644 --- a/aurorastation.dme +++ b/aurorastation.dme @@ -48,6 +48,7 @@ #include "code\__DEFINES\construction.dm" #include "code\__DEFINES\cooldowns.dm" #include "code\__DEFINES\damage_organs.dm" +#include "code\__DEFINES\directional.dm" #include "code\__DEFINES\dna.dm" #include "code\__DEFINES\documents.dm" #include "code\__DEFINES\drinks.dm" @@ -79,6 +80,8 @@ #include "code\__DEFINES\lighting.dm" #include "code\__DEFINES\logging.dm" #include "code\__DEFINES\machinery.dm" +#include "code\__DEFINES\mapping.dm" +#include "code\__DEFINES\maps.dm" #include "code\__DEFINES\materials.dm" #include "code\__DEFINES\math_physics.dm" #include "code\__DEFINES\maths.dm" @@ -91,6 +94,7 @@ #include "code\__DEFINES\modular_guns.dm" #include "code\__DEFINES\move_force.dm" #include "code\__DEFINES\movement.dm" +#include "code\__DEFINES\multiz.dm" #include "code\__DEFINES\obj.dm" #include "code\__DEFINES\organs.dm" #include "code\__DEFINES\origin_traits.dm" @@ -2395,25 +2399,30 @@ #include "code\modules\lock\lock.dm" #include "code\modules\lock\lock_construct.dm" #include "code\modules\makeshift\makeshift_reagents.dm" -#include "code\modules\maps\dmm_suite.dm" -#include "code\modules\maps\helper_landmarks.dm" -#include "code\modules\maps\map_template.dm" -#include "code\modules\maps\reader.dm" -#include "code\modules\maps\ruins.dm" -#include "code\modules\maps\swapmaps.dm" -#include "code\modules\maps\planet_types\asteroid.dm" -#include "code\modules\maps\planet_types\barren.dm" -#include "code\modules\maps\planet_types\crystal.dm" -#include "code\modules\maps\planet_types\desert.dm" -#include "code\modules\maps\planet_types\grass.dm" -#include "code\modules\maps\planet_types\jungle.dm" -#include "code\modules\maps\planet_types\lava.dm" -#include "code\modules\maps\planet_types\snow.dm" -#include "code\modules\maps\planet_types\lore\burzsia.dm" -#include "code\modules\maps\planet_types\lore\konyang.dm" -#include "code\modules\maps\planet_types\lore\srandmarr.dm" -#include "code\modules\maps\planet_types\lore\tauceti.dm" -#include "code\modules\maps\planet_types\lore\uueoaesa.dm" +#include "code\modules\mapping\dmm_suite.dm" +#include "code\modules\mapping\helper_landmarks.dm" +#include "code\modules\mapping\map_template.dm" +#include "code\modules\mapping\reader.dm" +#include "code\modules\mapping\ruins.dm" +#include "code\modules\mapping\swapmaps.dm" +#include "code\modules\mapping\planet_types\asteroid.dm" +#include "code\modules\mapping\planet_types\barren.dm" +#include "code\modules\mapping\planet_types\crystal.dm" +#include "code\modules\mapping\planet_types\desert.dm" +#include "code\modules\mapping\planet_types\grass.dm" +#include "code\modules\mapping\planet_types\jungle.dm" +#include "code\modules\mapping\planet_types\lava.dm" +#include "code\modules\mapping\planet_types\snow.dm" +#include "code\modules\mapping\planet_types\lore\burzsia.dm" +#include "code\modules\mapping\planet_types\lore\konyang.dm" +#include "code\modules\mapping\planet_types\lore\srandmarr.dm" +#include "code\modules\mapping\planet_types\lore\tauceti.dm" +#include "code\modules\mapping\planet_types\lore\uueoaesa.dm" +#include "code\modules\mapping\space_management\space_level.dm" +#include "code\modules\mapping\space_management\space_reservation.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\martial_arts\gunkata.dm" #include "code\modules\martial_arts\martial.dm" #include "code\modules\martial_arts\plasma_fist.dm" diff --git a/code/__DEFINES/_flags.dm b/code/__DEFINES/_flags.dm index 070bde8c683..e577d92a625 100644 --- a/code/__DEFINES/_flags.dm +++ b/code/__DEFINES/_flags.dm @@ -50,3 +50,16 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204 #define PASSDOORHATCH (1<<15) #define PASSTRACE (1<<16) //Used by turrets in the check_trajectory proc to target mobs hiding behind certain things (such as closets) #define PASSRAILING (1<<17) + +//TURF FLAGS +/// If a turf is an usused reservation turf awaiting assignment +#define UNUSED_RESERVATION_TURF BITFLAG(1) +/// If a turf is a reserved turf +#define RESERVATION_TURF BITFLAG(2) + +// Turf-only flags. +///Blocks the jaunting spell from accessing the turf +#define TURF_FLAG_NOJAUNT BITFLAG(3) + +///Used by shuttle movement to determine if it should be ignored by turf translation +#define TURF_FLAG_BACKGROUND BITFLAG(4) diff --git a/code/__DEFINES/directional.dm b/code/__DEFINES/directional.dm new file mode 100644 index 00000000000..e0d76122500 --- /dev/null +++ b/code/__DEFINES/directional.dm @@ -0,0 +1,14 @@ +// Byond direction defines, because I want to put them somewhere. +// #define NORTH 1 +// #define SOUTH 2 +// #define EAST 4 +// #define WEST 8 + +/// North direction as a string "[1]" +#define TEXT_NORTH "[NORTH]" +/// South direction as a string "[2]" +#define TEXT_SOUTH "[SOUTH]" +/// East direction as a string "[4]" +#define TEXT_EAST "[EAST]" +/// West direction as a string "[8]" +#define TEXT_WEST "[WEST]" diff --git a/code/__DEFINES/mapping.dm b/code/__DEFINES/mapping.dm new file mode 100644 index 00000000000..3c08679e2a4 --- /dev/null +++ b/code/__DEFINES/mapping.dm @@ -0,0 +1,6 @@ +// Defines for SSmapping's multiz_levels +/// TRUE if we're ok with going up +#define Z_LEVEL_UP 1 +/// TRUE if we're ok with going down +#define Z_LEVEL_DOWN 2 +#define LARGEST_Z_LEVEL_INDEX Z_LEVEL_DOWN diff --git a/code/__DEFINES/maps.dm b/code/__DEFINES/maps.dm new file mode 100644 index 00000000000..7776571e976 --- /dev/null +++ b/code/__DEFINES/maps.dm @@ -0,0 +1,44 @@ +// traits +// boolean - marks a level as having that property if present +#define ZTRAIT_CENTCOM "CentCom" +#define ZTRAIT_STATION "Station" +#define ZTRAIT_RESERVED "Transit/Reserved" +#define ZTRAIT_AWAY "Away Mission" +/* Aurora Snowflake */ +#define ZTRAIT_OVERMAP "Overmap" +#define ZTRAIT_EXPLANET "Exoplanet" + + +// Whether this z level is linked up/down. Bool. +#define ZTRAIT_UP "Up" +#define ZTRAIT_DOWN "Down" + +// enum - how space transitions should affect this level +#define ZTRAIT_LINKAGE "Linkage" + // UNAFFECTED if absent - no space transitions + #define UNAFFECTED null + // SELFLOOPING - space transitions always self-loop + #define SELFLOOPING "Self" + // CROSSLINKED - mixed in with the cross-linked space pool + #define CROSSLINKED "Cross" + +// default trait definitions, used by SSmapping +///Z level traits for CentCom +#define ZTRAITS_CENTCOM list(ZTRAIT_CENTCOM = TRUE, ZTRAIT_NOPHASE = TRUE) +///Z level traits for Space Station 13 +#define ZTRAITS_STATION list(ZTRAIT_LINKAGE = CROSSLINKED, ZTRAIT_STATION = TRUE) +///Z level traits for Away Missions +#define ZTRAITS_AWAY list(ZTRAIT_AWAY = TRUE) +///Z level traits for Overmap +#define ZTRAITS_OVERMAP list(ZTRAIT_OVERMAP = TRUE, ZTRAIT_LINKAGE = SELFLOOPING) +///Z level traits for Exoplanets +#define ZTRAITS_EXPLANET list(ZTRAIT_EXPLANET = TRUE, ZTRAIT_LINKAGE = SELFLOOPING) + +#define DL_NAME "name" +#define DL_TRAITS "traits" +#define DECLARE_LEVEL(NAME, TRAITS) list(DL_NAME = NAME, DL_TRAITS = TRAITS) + +// must correspond to _basemap.dm for things to work correctly +#define DEFAULT_MAP_TRAITS list(\ + DECLARE_LEVEL("CentCom", ZTRAITS_CENTCOM),\ +) diff --git a/code/__DEFINES/multiz.dm b/code/__DEFINES/multiz.dm new file mode 100644 index 00000000000..370eaa8ba45 --- /dev/null +++ b/code/__DEFINES/multiz.dm @@ -0,0 +1,8 @@ +/// Attempt to get the turf below the provided one according to Z traits +#define GET_TURF_BELOW(turf) ( \ + (turf.turf_flags & RESERVATION_TURF) ? SSmapping.get_reservation_from_turf(turf)?.get_turf_below(turf) : \ + (!(turf) || !length(SSmapping.multiz_levels) || !SSmapping.multiz_levels[(turf).z][Z_LEVEL_DOWN]) ? null : get_step((turf), DOWN)) +/// Attempt to get the turf above the provided one according to Z traits +#define GET_TURF_ABOVE(turf) ( \ + (turf.turf_flags & RESERVATION_TURF) ? SSmapping.get_reservation_from_turf(turf)?.get_turf_above(turf) : \ + (!(turf) || !length(SSmapping.multiz_levels) || !SSmapping.multiz_levels[(turf).z][Z_LEVEL_UP]) ? null : get_step((turf), UP)) diff --git a/code/__DEFINES/turfs.dm b/code/__DEFINES/turfs.dm index 5ca90cbd7fe..9af116da7ab 100644 --- a/code/__DEFINES/turfs.dm +++ b/code/__DEFINES/turfs.dm @@ -106,32 +106,6 @@ AURORA SHIT ################################*/ -// Turf-only flags. -///Blocks the jaunting spell from accessing the turf -#define TURF_FLAG_NOJAUNT BITFLAG(1) - -///Used by shuttle movement to determine if it should be ignored by turf translation -#define TURF_FLAG_BACKGROUND BITFLAG(2) - - -/** - * Get the turf above the current atom, if any - * - * Returns a `/turf` if there's a turf on the Z-level above, `null` otherwise - * - * * atom - The `/atom` you want to know the above turf of - */ -#define GET_ABOVE(atom) (HasAbove(atom.z) ? get_step(atom, UP) : null) - -/** - * Get the turf below the current atom, if any - * - * Returns a `/turf` if there's a turf on the Z-level below, `null` otherwise - * - * * atom - The `/atom` you want to know the below turf of - */ -#define GET_BELOW(atom) (HasBelow(atom.z) ? get_step(atom, DOWN) : null) - #define NORTH_OF_TURF(T) locate(T.x, T.y + 1, T.z) #define EAST_OF_TURF(T) locate(T.x + 1, T.y, T.z) #define SOUTH_OF_TURF(T) locate(T.x, T.y - 1, T.z) diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index e36db9e3c23..a9cd859198d 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -347,7 +347,7 @@ for(var/turf/T in view(usr.client.view + 3, usr)) // slightly extra to account for moving while looking for openness if(T.density) continue - var/turf/above_turf = GetAbove(T) + var/turf/above_turf = GET_TURF_ABOVE(T) if(!isopenspace(above_turf)) continue var/image/up_image = image(icon = 'icons/mob/screen/generic.dmi', icon_state = "arrow_up", loc = T) @@ -356,7 +356,8 @@ usr << up_image QDEL_IN(up_image, 12) return - var/turf/T = GetAbove(usr) + var/turf/T1 = get_turf(usr) + var/turf/T = GET_TURF_ABOVE(T1) if (!T) to_chat(usr, SPAN_NOTICE("There is nothing above you!")) else if (T.is_hole) diff --git a/code/controllers/subsystems/explosives.dm b/code/controllers/subsystems/explosives.dm index f44d7754181..cb893b814ef 100644 --- a/code/controllers/subsystems/explosives.dm +++ b/code/controllers/subsystems/explosives.dm @@ -73,10 +73,10 @@ SUBSYSTEM_DEF(explosives) // Handles recursive propagation of explosions. if(devastation_range > 2 || heavy_impact_range > 2) - if(HasAbove(epicenter.z) && z_transfer & UP) - global.explosion(GetAbove(epicenter), max(0, devastation_range - 2), max(0, heavy_impact_range - 2), max(0, light_impact_range - 2), max(0, flash_range - 2), 0, UP, spreading = FALSE) - if(HasBelow(epicenter.z) && z_transfer & DOWN) - global.explosion(GetBelow(epicenter), max(0, devastation_range - 2), max(0, heavy_impact_range - 2), max(0, light_impact_range - 2), max(0, flash_range - 2), 0, DOWN, spreading = FALSE) + if(GET_TURF_ABOVE(epicenter) && z_transfer & UP) + global.explosion(GET_TURF_ABOVE(epicenter), max(0, devastation_range - 2), max(0, heavy_impact_range - 2), max(0, light_impact_range - 2), max(0, flash_range - 2), 0, UP, spreading = FALSE) + if(GET_TURF_BELOW(epicenter) && z_transfer & DOWN) + global.explosion(GET_TURF_BELOW(epicenter), max(0, devastation_range - 2), max(0, heavy_impact_range - 2), max(0, light_impact_range - 2), max(0, flash_range - 2), 0, DOWN, spreading = FALSE) var/max_range = max(devastation_range, heavy_impact_range, light_impact_range, flash_range) @@ -258,17 +258,17 @@ SUBSYSTEM_DEF(explosives) power -= O.explosion_resistance if (power >= GLOB.config.iterative_explosives_z_threshold) - if ((z_transfer & UP) && HasAbove(epicenter.z)) + if ((z_transfer & UP) && GET_TURF_ABOVE(epicenter)) var/datum/explosiondata/data = new - data.epicenter = GetAbove(epicenter) + data.epicenter = GET_TURF_ABOVE(epicenter) data.rec_pow = (power * GLOB.config.iterative_explosives_z_multiplier) - GLOB.config.iterative_explosives_z_subtraction data.z_transfer = UP data.spreading = TRUE queue(data) - if ((z_transfer & DOWN) && HasBelow(epicenter.z)) + if ((z_transfer & DOWN) && GET_TURF_BELOW(epicenter)) var/datum/explosiondata/data = new - data.epicenter = GetBelow(epicenter) + data.epicenter = GET_TURF_BELOW(epicenter) data.rec_pow = (power * GLOB.config.iterative_explosives_z_multiplier) - GLOB.config.iterative_explosives_z_subtraction data.z_transfer = DOWN data.spreading = TRUE diff --git a/code/controllers/subsystems/falling.dm b/code/controllers/subsystems/falling.dm index 3f6a0dca093..a2bd77bedc7 100644 --- a/code/controllers/subsystems/falling.dm +++ b/code/controllers/subsystems/falling.dm @@ -39,7 +39,8 @@ SUBSYSTEM_DEF(falling) REMOVE_AND_CONTINUE // Get the below turf. - var/turf/below = GetBelow(victim) + var/turf/T = get_turf(victim) + var/turf/below = GET_TURF_BELOW(T) if (!below) REMOVE_AND_CONTINUE diff --git a/code/controllers/subsystems/initialization/atlas.dm b/code/controllers/subsystems/initialization/atlas.dm index 95182cc6cda..16063b632be 100644 --- a/code/controllers/subsystems/initialization/atlas.dm +++ b/code/controllers/subsystems/initialization/atlas.dm @@ -137,7 +137,7 @@ SUBSYSTEM_DEF(atlas) ) /datum/controller/subsystem/atlas/stat_entry(msg) - msg = "W:{X:[world.maxx] Y:[world.maxy] Z:[world.maxz]} ZL:[GLOB.z_levels]" + msg = "W:{X:[world.maxx] Y:[world.maxy] Z:[world.maxz]} ZL:[length(SSmapping.z_list)]" return ..() /datum/controller/subsystem/atlas/Initialize(timeofday) @@ -223,30 +223,57 @@ SUBSYSTEM_DEF(atlas) var/static/regex/mapregex = new(".+\\.dmm$") var/list/files = flist(directory) sortTim(files, GLOBAL_PROC_REF(cmp_text_asc)) + var/list/filemaps_to_load + for(var/file in files) + if(mapregex.Find(file)) + filemaps_to_load += list(file) + var/mfile var/first_dmm = TRUE var/time - for (var/i in 1 to files.len) - mfile = files[i] - if (!mapregex.Find(mfile)) - continue + + var/is_first = TRUE + for(var/i in 1 to length(filemaps_to_load)) + mfile = filemaps_to_load[i] log_subsystem_atlas("Loading '[mfile]'.") time = world.time mfile = "[directory][mfile]" - var/target_z = 0 if (overwrite_default_z && first_dmm) - target_z = 1 first_dmm = FALSE log_subsystem_atlas("Overwriting first Z.") - if (!maploader.load_map(file(mfile), 0, 0, target_z, no_changeturf = TRUE)) + var/list/trait = ZTRAITS_STATION + + //We're NOT loading the first level + if(!is_first) + //Last level is centcomm, noone goes in or out + if(i == length(filemaps_to_load)) + trait += list(ZTRAIT_UP = FALSE, ZTRAIT_DOWN = FALSE) + //Last level in the actual stack, can only go down + else if(i == (length(filemaps_to_load) - 1)) + trait += list(ZTRAIT_UP = FALSE, ZTRAIT_DOWN = TRUE) + //Bidirectional movement + else + trait += list(ZTRAIT_UP = TRUE, ZTRAIT_DOWN = TRUE) + + //We're loading the first level, usually it has something above it + else if(length(filemaps_to_load) >= 2) + trait += list(ZTRAIT_UP = TRUE, ZTRAIT_DOWN = FALSE) + else //Special case for single-level maps + trait += list(ZTRAIT_UP = FALSE, ZTRAIT_DOWN = FALSE) + + var/datum/space_level/level = SSmapping.add_new_zlevel(name, trait, contain_turfs = FALSE) + + if (!maploader.load_map(file(mfile), 0, 0, level.z_value, no_changeturf = TRUE)) log_subsystem_atlas("Failed to load '[mfile]'!") else log_subsystem_atlas("Loaded level in [(world.time - time)/10] seconds.") + is_first = FALSE + .++ CHECK_TICK diff --git a/code/controllers/subsystems/mapping.dm b/code/controllers/subsystems/mapping.dm index 9a87b21fcf9..b2bb210bb5f 100644 --- a/code/controllers/subsystems/mapping.dm +++ b/code/controllers/subsystems/mapping.dm @@ -10,6 +10,25 @@ SUBSYSTEM_DEF(mapping) var/list/submaps = list() var/list/submap_archetypes = list() + var/list/used_turfs = list() //list of turf = datum/turf_reservation -- Currently unused + + /// List of z level (as number) -> list of all z levels vertically connected to ours + /// Useful for fast grouping lookups and such + var/list/z_level_to_stack = list() + + ///list of all z level datums in the order of their z (z level 1 is at index 1, etc.) + var/list/datum/space_level/z_list = list() + + ///list of all z level indices that form multiz connections and whether theyre linked up or down. + ///list of lists, inner lists are of the form: list("up or down link direction" = TRUE) + var/list/multiz_levels = list() + + /// list of traits and their associated z leves + var/list/z_trait_levels = list() + + /// True when in the process of adding a new Z-level, global locking + var/adding_new_zlevel = FALSE + /datum/controller/subsystem/mapping/Initialize(timeofday) // Load templates and build away sites. preloadTemplates() @@ -72,6 +91,40 @@ SUBSYSTEM_DEF(mapping) else if(istype(MT, /datum/map_template/ruin/away_site)) away_sites_templates[MT.id] = MT +/datum/controller/subsystem/mapping/proc/generate_linkages_for_z_level(z_level) + if(!isnum(z_level) || z_level <= 0) + return FALSE + + if(multiz_levels.len < z_level) + multiz_levels.len = z_level + + var/z_above = level_trait(z_level, ZTRAIT_UP) + var/z_below = level_trait(z_level, ZTRAIT_DOWN) + if(!(z_above == TRUE || z_above == FALSE || z_above == null) || !(z_below == TRUE || z_below == FALSE || z_below == null)) + stack_trace("Warning, numeric mapping offsets are deprecated. Instead, mark z level connections by setting UP/DOWN to true if the connection is allowed") + multiz_levels[z_level] = new /list(LARGEST_Z_LEVEL_INDEX) + multiz_levels[z_level][Z_LEVEL_UP] = !!z_above + multiz_levels[z_level][Z_LEVEL_DOWN] = !!z_below + +/// Takes a z level datum, and tells the mapping subsystem to manage it +/// Also handles things like plane offset generation, and other things that happen on a z level to z level basis +/datum/controller/subsystem/mapping/proc/manage_z_level(datum/space_level/new_z, filled_with_space, contain_turfs = TRUE) + // First, add the z + z_list += new_z + + // Then we build our lookup lists + var/z_value = new_z.z_value + + z_level_to_stack.len += 1 + // Bare minimum we have ourselves + z_level_to_stack[z_value] = list(z_value) + +//Placeholder for now +/datum/controller/subsystem/mapping/proc/get_reservation_from_turf(turf/T) + RETURN_TYPE(/datum/turf_reservation) + return used_turfs[T] + + /proc/generateMapList(filename) var/list/potentialMaps = list() var/list/Lines = world.file2list(filename) diff --git a/code/controllers/subsystems/zcopy.dm b/code/controllers/subsystems/zcopy.dm index ba0081f6e05..aa7bdda7d48 100644 --- a/code/controllers/subsystems/zcopy.dm +++ b/code/controllers/subsystems/zcopy.dm @@ -115,7 +115,7 @@ SUBSYSTEM_DEF(zcopy) zlev_maximums = new(world.maxz) var/start_zlev = 1 for (var/z in 1 to world.maxz) - if (!HasAbove(z)) + if (!SSmapping.multiz_levels[z][Z_LEVEL_UP]) for (var/member_zlev in start_zlev to z) zlev_maximums[member_zlev] = z if (z - start_zlev > OPENTURF_MAX_DEPTH) diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index cc96ac8baf4..5edefb52a15 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -364,7 +364,7 @@ return if(SSatlas.current_map.use_overmap) - overmap_spacetravel(get_turf(src), src) + INVOKE_ASYNC(GLOBAL_PROC, GLOBAL_PROC_REF(overmap_spacetravel), get_turf(src), src) return var/move_to_z = src.get_transit_zlevel() diff --git a/code/game/gamemodes/endgame/supermatter_cascade/blob.dm b/code/game/gamemodes/endgame/supermatter_cascade/blob.dm index 9c8f994ce38..7f050dde86a 100644 --- a/code/game/gamemodes/endgame/supermatter_cascade/blob.dm +++ b/code/game/gamemodes/endgame/supermatter_cascade/blob.dm @@ -35,8 +35,8 @@ var/pdir = pick(avail_dirs) avail_dirs -= pdir var/turf/T = get_step(src, pdir) - var/turf/A = GetAbove(T) - var/turf/B = GetBelow(T) + var/turf/A = GET_TURF_ABOVE(T) + var/turf/B = GET_TURF_BELOW(T) // EXPAND if(!istype(T,type)) diff --git a/code/game/sound.dm b/code/game/sound.dm index 5afcee00b5d..82df94a576d 100644 --- a/code/game/sound.dm +++ b/code/game/sound.dm @@ -85,8 +85,8 @@ . = list()//output everything that successfully heard the sound - var/turf/above_turf = GetAbove(turf_source) - var/turf/below_turf = GetBelow(turf_source) + var/turf/above_turf = GET_TURF_ABOVE(turf_source) + var/turf/below_turf = GET_TURF_BELOW(turf_source) if(ignore_walls) diff --git a/code/game/turfs/flooring/flooring_premade_other.dm b/code/game/turfs/flooring/flooring_premade_other.dm index 9b69c145da9..00174e98592 100644 --- a/code/game/turfs/flooring/flooring_premade_other.dm +++ b/code/game/turfs/flooring/flooring_premade_other.dm @@ -56,7 +56,6 @@ icon_state = "diona0" footstep_sound = /singleton/sound_category/grass_footstep initial_flooring = /singleton/flooring/diona - turf_flags = TURF_REMOVE_SHOVEL|TURF_REMOVE_WELDER /turf/simulated/floor/diona/airless initial_gas = null diff --git a/code/game/turfs/simulated/floor_attackby.dm b/code/game/turfs/simulated/floor_attackby.dm index 411945741f5..45b5f9fb6ea 100644 --- a/code/game/turfs/simulated/floor_attackby.dm +++ b/code/game/turfs/simulated/floor_attackby.dm @@ -95,7 +95,7 @@ if(broken || burnt) playsound(src, 'sound/items/crowbar_tile.ogg', 80, 1) visible_message(SPAN_NOTICE("[user] has begun prying off the damaged plating.")) - var/turf/T = GetBelow(src) + var/turf/T = GET_TURF_BELOW(src) if(T) T.visible_message(SPAN_WARNING("The ceiling above looks as if it's being pried off.")) if(do_after(user, 10 SECONDS)) diff --git a/code/game/turfs/simulated/wall_attacks.dm b/code/game/turfs/simulated/wall_attacks.dm index 66485f2b194..0143d65312b 100644 --- a/code/game/turfs/simulated/wall_attacks.dm +++ b/code/game/turfs/simulated/wall_attacks.dm @@ -74,7 +74,8 @@ if(ishuman(user) && user.a_intent == I_GRAB) var/mob/living/carbon/human/H = user - var/turf/destination = GetAbove(H) + var/turf/current_turf = get_turf(H) + var/turf/destination = GET_TURF_ABOVE(current_turf) if(destination) var/turf/start = get_turf(H) diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm index c05c4f96b42..f38c6759cb8 100644 --- a/code/game/turfs/space/space.dm +++ b/code/game/turfs/space/space.dm @@ -53,7 +53,7 @@ // Cleanup cached z_eventually_space values above us. if (above) var/turf/T = src - while ((T = GetAbove(T))) + while ((T = GET_TURF_ABOVE(T))) T.z_eventually_space = FALSE return ..() diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 3a551be472f..8df6e1b1923 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -4,7 +4,6 @@ layer = TURF_LAYER - var/turf_flags var/holy = 0 // Initial air contents (in moles) @@ -60,6 +59,9 @@ ///used for guaranteeing there is only one oranges_ear per turf when assigned, speeds up view() iteration var/mob/oranges_ear/assigned_oranges_ear + /// Turf bitflags, see code/__DEFINES/flags.dm + var/turf_flags = NONE + /// How pathing algorithm will check if this turf is passable by itself (not including content checks). By default it's just density check. /// WARNING: Currently to use a density shortcircuiting this does not support dense turfs with special allow through function var/pathing_pass_method = TURF_PATHING_PASS_DENSITY @@ -479,7 +481,7 @@ var/const/enterloopsanity = 100 * @return TRUE if a roof has been spawned, FALSE if not. */ /turf/proc/spawn_roof(flags = 0) - var/turf/above = GetAbove(src) + var/turf/above = GET_TURF_ABOVE(src) if (!above) return FALSE @@ -501,11 +503,11 @@ var/const/enterloopsanity = 100 * flag is present on the source turf. */ /turf/proc/cleanup_roof() - if (!HasAbove(z)) + if (!SSmapping.multiz_levels[z][Z_LEVEL_UP]) return if (roof_flags & ROOF_CLEANUP) - var/turf/above = GetAbove(src) + var/turf/above = GET_TURF_ABOVE(src) if (!above || isopenturf(above)) return @@ -582,11 +584,11 @@ var/const/enterloopsanity = 100 // If we are in a multiz volume and not already inside, we return // the outside value of the highest unenclosed turf in the stack. - if(HasAbove(z)) + if(SSmapping.multiz_levels[z][Z_LEVEL_UP]) . = OUTSIDE_YES // assume for the moment we're unroofed until we learn otherwise. var/turf/top_of_stack = src - while(HasAbove(top_of_stack.z)) - var/turf/next_turf = GetAbove(top_of_stack) + while(GET_TURF_ABOVE(top_of_stack)) + var/turf/next_turf = GET_TURF_ABOVE(top_of_stack) if(!next_turf.is_open()) return OUTSIDE_NO top_of_stack = next_turf @@ -604,13 +606,13 @@ var/const/enterloopsanity = 100 last_outside_check = OUTSIDE_UNCERTAIN - if(!HasBelow(z)) + if(!GET_TURF_BELOW(src)) return TRUE // Invalidate the outside check cache for turfs below us. var/turf/checking = src - while(HasBelow(checking.z)) - checking = GetBelow(checking) + while(GET_TURF_BELOW(checking)) + checking = GET_TURF_BELOW(checking) if(!isturf(checking)) break checking.last_outside_check = OUTSIDE_UNCERTAIN @@ -640,7 +642,7 @@ var/const/enterloopsanity = 100 // Propagate our weather downwards if we permit it. if(force_update_below || (is_open() && .)) - var/turf/below = GetBelow(src) + var/turf/below = GET_TURF_BELOW(src) if(below) below.update_weather(new_weather) diff --git a/code/game/turfs/turf_changing.dm b/code/game/turfs/turf_changing.dm index 3c1c97b70eb..cfbdf73d445 100644 --- a/code/game/turfs/turf_changing.dm +++ b/code/game/turfs/turf_changing.dm @@ -39,7 +39,7 @@ return // This makes sure that turfs are not changed to space when there's a multi-z turf below - if(ispath(N, /turf/space) && HasBelow(z) && !ignore_override) + if(ispath(N, /turf/space) && GET_TURF_BELOW(src) && !ignore_override) N = openspace_override_type || /turf/simulated/open/airless var/obj/fire/old_fire = fire diff --git a/code/game/world.dm b/code/game/world.dm index e2eb56af80f..7fa1ef74e12 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -479,6 +479,8 @@ var/list/world_api_rate_limit = list() else return TRUE +/world/proc/incrementMaxZ() + maxz++ /world/proc/change_fps(new_value = 20) if(new_value <= 0) diff --git a/code/modules/atmospherics/he_pipes.dm b/code/modules/atmospherics/he_pipes.dm index dc85456730e..006ddb4486d 100644 --- a/code/modules/atmospherics/he_pipes.dm +++ b/code/modules/atmospherics/he_pipes.dm @@ -58,8 +58,10 @@ ..() else var/datum/gas_mixture/pipe_air = return_air() + var/turf/T = get_turf(loc) + var/turf/turf_above = GET_TURF_ABOVE(T) - if(istype(loc, /turf/space) || (isopenturf(loc) && (istype(GetBelow(loc), /turf/space) || istype(GetAbove(loc), /turf/space)))) + if(istype(loc, /turf/space) || (isopenturf(loc) && (istype(GET_TURF_BELOW(T), /turf/space) || istype(turf_above, /turf/space)))) parent.radiate_heat_to_space(surface, 1) else if(istype(loc, /turf/simulated/lava)) diff --git a/code/modules/clothing/spacesuits/rig/modules/utility.dm b/code/modules/clothing/spacesuits/rig/modules/utility.dm index 6d189d30181..103557d8af3 100644 --- a/code/modules/clothing/spacesuits/rig/modules/utility.dm +++ b/code/modules/clothing/spacesuits/rig/modules/utility.dm @@ -655,7 +655,7 @@ var/obj/structure/lattice/L = locate() in T if(L) return L.name - var/turf/leapBelow = GetBelow(T) + var/turf/leapBelow = GET_TURF_BELOW(T) if(leapBelow.density) return leapBelow.name else if(T.contains_dense_objects()) @@ -718,7 +718,8 @@ H.throw_at(T, leapDistance, 1, spin = FALSE) return TRUE else - var/turf/simulated/open/TA = GetAbove(src) + var/turf/current_turf = get_turf(src) + var/turf/simulated/open/TA = GET_TURF_ABOVE(current_turf) if (!istype(TA)) to_chat(user, SPAN_WARNING("There is a ceiling above you that stop you from leaping upwards!")) return FALSE diff --git a/code/modules/lighting/lighting_corner.dm b/code/modules/lighting/lighting_corner.dm index 85f227c6745..f8fa2082fb5 100644 --- a/code/modules/lighting/lighting_corner.dm +++ b/code/modules/lighting/lighting_corner.dm @@ -136,7 +136,7 @@ var/list/REVERSE_LIGHTING_CORNER_DIAGONAL = list(0, 0, 0, 0, 3, 4, 0, 0, 2, 1) #define AVERAGE_BELOW_CORNER(Tt, Ti) \ if (TURF_IS_MIMICING(Tt)) { \ - T = GET_BELOW(Tt); \ + T = GET_TURF_BELOW(Tt); \ if (T && T.corners && TURF_IS_DYNAMICALLY_LIT_UNSAFE(T)) { \ C = T.corners[Ti]; \ if (C) { \ @@ -150,7 +150,7 @@ var/list/REVERSE_LIGHTING_CORNER_DIAGONAL = list(0, 0, 0, 0, 3, 4, 0, 0, 2, 1) #define UPDATE_ABOVE_CORNER(Tt, Ti) \ if (Tt) { \ - T = GET_ABOVE(Tt); \ + T = GET_TURF_ABOVE(Tt); \ if (TURF_IS_MIMICING(T) && TURF_IS_DYNAMICALLY_LIT_UNSAFE(T)) { \ if (!T.corners) { \ T.generate_missing_corners(); \ diff --git a/code/modules/maps/dmm_suite.dm b/code/modules/mapping/dmm_suite.dm similarity index 100% rename from code/modules/maps/dmm_suite.dm rename to code/modules/mapping/dmm_suite.dm diff --git a/code/modules/maps/helper_landmarks.dm b/code/modules/mapping/helper_landmarks.dm similarity index 100% rename from code/modules/maps/helper_landmarks.dm rename to code/modules/mapping/helper_landmarks.dm diff --git a/code/modules/maps/map_template.dm b/code/modules/mapping/map_template.dm similarity index 90% rename from code/modules/maps/map_template.dm rename to code/modules/mapping/map_template.dm index b2562626342..54c0eb8656b 100644 --- a/code/modules/maps/map_template.dm +++ b/code/modules/mapping/map_template.dm @@ -58,8 +58,33 @@ //Since SSicon_smooth.add_to_queue() manually wakes the subsystem, we have to use enable/disable. SSicon_smooth.can_fire = FALSE - for (var/mappath in mappaths) - var/datum/map_load_metadata/M = maploader.load_map(file(mappath), x, y, no_changeturf = no_changeturf) + var/is_first = TRUE + + for(var/i in 1 to length(mappaths)) + var/mappath = mappaths[i] + + var/list/trait = ZTRAITS_AWAY + + //Second or subsequent map file + if(!is_first) + //Last map file in a multi level map, can only go down + if(i == length(mappaths)) + trait += list(ZTRAIT_UP = FALSE, ZTRAIT_DOWN = TRUE) + //Intermediate map file, can go up and down + else + trait += list(ZTRAIT_UP = TRUE, ZTRAIT_DOWN = TRUE) + + //First map file + else + //Multi-level map + if(length(mappaths) >= 2) + trait += list(ZTRAIT_UP = TRUE, ZTRAIT_DOWN = FALSE) + //Single-level map + else + trait += list(ZTRAIT_UP = FALSE, ZTRAIT_DOWN = FALSE) + + var/datum/space_level/level = SSmapping.add_new_zlevel(name, trait, contain_turfs = FALSE) + var/datum/map_load_metadata/M = maploader.load_map(file(mappath), x, y, level.z_value, no_changeturf = no_changeturf) if (M) bounds = extend_bounds_if_needed(bounds, M.bounds) atoms_to_initialise += M.atoms_to_initialise @@ -67,6 +92,8 @@ SSicon_smooth.can_fire = TRUE return FALSE + is_first = FALSE + for (var/z_index = bounds[MAP_MINZ]; z_index <= bounds[MAP_MAXZ]; z_index++) if (accessibility_weight) SSatlas.current_map.accessible_z_levels[num2text(z_index)] = accessibility_weight diff --git a/code/modules/maps/planet_types/asteroid.dm b/code/modules/mapping/planet_types/asteroid.dm similarity index 100% rename from code/modules/maps/planet_types/asteroid.dm rename to code/modules/mapping/planet_types/asteroid.dm diff --git a/code/modules/maps/planet_types/barren.dm b/code/modules/mapping/planet_types/barren.dm similarity index 100% rename from code/modules/maps/planet_types/barren.dm rename to code/modules/mapping/planet_types/barren.dm diff --git a/code/modules/maps/planet_types/crystal.dm b/code/modules/mapping/planet_types/crystal.dm similarity index 100% rename from code/modules/maps/planet_types/crystal.dm rename to code/modules/mapping/planet_types/crystal.dm diff --git a/code/modules/maps/planet_types/desert.dm b/code/modules/mapping/planet_types/desert.dm similarity index 100% rename from code/modules/maps/planet_types/desert.dm rename to code/modules/mapping/planet_types/desert.dm diff --git a/code/modules/maps/planet_types/grass.dm b/code/modules/mapping/planet_types/grass.dm similarity index 100% rename from code/modules/maps/planet_types/grass.dm rename to code/modules/mapping/planet_types/grass.dm diff --git a/code/modules/maps/planet_types/jungle.dm b/code/modules/mapping/planet_types/jungle.dm similarity index 100% rename from code/modules/maps/planet_types/jungle.dm rename to code/modules/mapping/planet_types/jungle.dm diff --git a/code/modules/maps/planet_types/lava.dm b/code/modules/mapping/planet_types/lava.dm similarity index 100% rename from code/modules/maps/planet_types/lava.dm rename to code/modules/mapping/planet_types/lava.dm diff --git a/code/modules/maps/planet_types/lore/burzsia.dm b/code/modules/mapping/planet_types/lore/burzsia.dm similarity index 100% rename from code/modules/maps/planet_types/lore/burzsia.dm rename to code/modules/mapping/planet_types/lore/burzsia.dm diff --git a/code/modules/maps/planet_types/lore/konyang.dm b/code/modules/mapping/planet_types/lore/konyang.dm similarity index 100% rename from code/modules/maps/planet_types/lore/konyang.dm rename to code/modules/mapping/planet_types/lore/konyang.dm diff --git a/code/modules/maps/planet_types/lore/srandmarr.dm b/code/modules/mapping/planet_types/lore/srandmarr.dm similarity index 100% rename from code/modules/maps/planet_types/lore/srandmarr.dm rename to code/modules/mapping/planet_types/lore/srandmarr.dm diff --git a/code/modules/maps/planet_types/lore/tauceti.dm b/code/modules/mapping/planet_types/lore/tauceti.dm similarity index 100% rename from code/modules/maps/planet_types/lore/tauceti.dm rename to code/modules/mapping/planet_types/lore/tauceti.dm diff --git a/code/modules/maps/planet_types/lore/uueoaesa.dm b/code/modules/mapping/planet_types/lore/uueoaesa.dm similarity index 100% rename from code/modules/maps/planet_types/lore/uueoaesa.dm rename to code/modules/mapping/planet_types/lore/uueoaesa.dm diff --git a/code/modules/maps/planet_types/snow.dm b/code/modules/mapping/planet_types/snow.dm similarity index 100% rename from code/modules/maps/planet_types/snow.dm rename to code/modules/mapping/planet_types/snow.dm diff --git a/code/modules/maps/reader.dm b/code/modules/mapping/reader.dm similarity index 99% rename from code/modules/maps/reader.dm rename to code/modules/mapping/reader.dm index c0f64dd4b9d..5857416783e 100644 --- a/code/modules/maps/reader.dm +++ b/code/modules/mapping/reader.dm @@ -110,7 +110,7 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new) var/zcrd = text2num(dmmRegex.group[5]) + z_offset - 1 var/zexpansion = zcrd > world.maxz - if(zexpansion) + if(zexpansion && !measureOnly) // don't actually expand the world if we're only measuring bounds if(cropMap) continue else diff --git a/code/modules/maps/ruins.dm b/code/modules/mapping/ruins.dm similarity index 100% rename from code/modules/maps/ruins.dm rename to code/modules/mapping/ruins.dm 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..1747806cb21 --- /dev/null +++ b/code/modules/mapping/space_management/space_level.dm @@ -0,0 +1,22 @@ +/datum/space_level + var/name = "NAME MISSING" + 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, list/new_traits = list()) + z_value = new_z + name = new_name + traits = new_traits + + if (islist(new_traits)) + for (var/trait in new_traits) + SSmapping.z_trait_levels[trait] += list(new_z) + else // in case a single trait is passed in + SSmapping.z_trait_levels[new_traits] += list(new_z) + + + set_linkage(new_traits[ZTRAIT_LINKAGE]) diff --git a/code/modules/mapping/space_management/space_reservation.dm b/code/modules/mapping/space_management/space_reservation.dm new file mode 100644 index 00000000000..77bc1cfebb2 --- /dev/null +++ b/code/modules/mapping/space_management/space_reservation.dm @@ -0,0 +1,95 @@ +/* THIS IS ONLY A PLACEHOLDER AND DOESN'T WORK */ + +//Yes, they can only be rectangular. +//Yes, I'm sorry. +/datum/turf_reservation + /// All turfs that we've reserved + var/list/reserved_turfs = list() + + /// Turfs around the reservation for cordoning + var/list/cordon_turfs = list() + + /// Area of turfs next to the cordon to fill with pre_cordon_area's + var/list/pre_cordon_turfs = list() + + /// The width of the reservation + var/width = 0 + + /// The height of the reservation + var/height = 0 + + /// The z stack size of the reservation. Note that reservations are ALWAYS reserved from the bottom up + var/z_size = 0 + + /// List of the bottom left turfs. Indexed by what their z index for this reservation is + var/list/bottom_left_turfs = list() + + /// List of the top right turfs. Indexed by what their z index for this reservation is + var/list/top_right_turfs = list() + + /// The turf type the reservation is initially made with + var/turf_type = /turf/space + + ///Distance away from the cordon where we can put a "sort-cordon" and run some extra code (see make_repel). 0 makes nothing happen + var/pre_cordon_distance = 0 + +/// Calculates the effective bounds information for the given turf. Returns a list of the information, or null if not applicable. +/datum/turf_reservation/proc/calculate_turf_bounds_information(turf/target) + for(var/z_idx in 1 to z_size) + var/turf/bottom_left = bottom_left_turfs[z_idx] + var/turf/top_right = top_right_turfs[z_idx] + var/bl_x = bottom_left.x + var/bl_y = bottom_left.y + var/tr_x = top_right.x + var/tr_y = top_right.y + + if(target.x < bl_x) + continue + + if(target.y < bl_y) + continue + + if(target.x > tr_x) + continue + + if(target.y > tr_y) + continue + + var/list/return_information = list() + return_information["z_idx"] = z_idx + return_information["offset_x"] = target.x - bl_x + return_information["offset_y"] = target.y - bl_y + return return_information + return null + +/// Gets the turf below the given target. Returns null if there is no turf below the target +/datum/turf_reservation/proc/get_turf_below(turf/target) + var/list/bounds_info = calculate_turf_bounds_information(target) + if(isnull(bounds_info)) + return null + + var/z_idx = bounds_info["z_idx"] + // check what z level, if its the max, then there is no turf below + if(z_idx == z_size) + return null + + var/offset_x = bounds_info["offset_x"] + var/offset_y = bounds_info["offset_y"] + var/turf/bottom_left = bottom_left_turfs[z_idx + 1] + return locate(bottom_left.x + offset_x, bottom_left.y + offset_y, bottom_left.z) + +/// Gets the turf above the given target. Returns null if there is no turf above the target +/datum/turf_reservation/proc/get_turf_above(turf/target) + var/list/bounds_info = calculate_turf_bounds_information(target) + if(isnull(bounds_info)) + return null + + var/z_idx = bounds_info["z_idx"] + // check what z level, if its the min, then there is no turf above + if(z_idx == 1) + return null + + var/offset_x = bounds_info["offset_x"] + var/offset_y = bounds_info["offset_y"] + var/turf/bottom_left = bottom_left_turfs[z_idx - 1] + return locate(bottom_left.x + offset_x, bottom_left.y + offset_y, bottom_left.z) diff --git a/code/modules/mapping/space_management/space_transition.dm b/code/modules/mapping/space_management/space_transition.dm new file mode 100644 index 00000000000..b4e13703805 --- /dev/null +++ b/code/modules/mapping/space_management/space_transition.dm @@ -0,0 +1,6 @@ +/datum/space_level/proc/set_linkage(new_linkage) + linkage = new_linkage + if(linkage == SELFLOOPING) + neigbours = list(TEXT_NORTH,TEXT_SOUTH,TEXT_EAST,TEXT_WEST) + for(var/A in neigbours) + neigbours[A] = src diff --git a/code/modules/mapping/space_management/traits.dm b/code/modules/mapping/space_management/traits.dm new file mode 100644 index 00000000000..315464d62fd --- /dev/null +++ b/code/modules/mapping/space_management/traits.dm @@ -0,0 +1,16 @@ +/// Look up levels[z].traits[trait] +/datum/controller/subsystem/mapping/proc/level_trait(z, trait) + if (!isnum(z) || z < 1) + return null + if (z_list) + if (z > z_list.len) + stack_trace("Unmanaged z-level [z]! maxz = [world.maxz], z_list.len = [z_list.len]") + return list() + var/datum/space_level/S = z_list[z] + return S.traits[trait] + else + var/list/default = DEFAULT_MAP_TRAITS + if (z > default.len) + stack_trace("Unmanaged z-level [z]! maxz = [world.maxz], default.len = [default.len]") + return list() + return default[z][DL_TRAITS][trait] 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..d9c2d797106 --- /dev/null +++ b/code/modules/mapping/space_management/zlevel_manager.dm @@ -0,0 +1,21 @@ +/// Generates a real, honest to god new z level. Will create the actual space, and also generate a datum that holds info about the new plot of land +/// Accepts the name, traits list, datum type, and if we should manage the turfs we create +/datum/controller/subsystem/mapping/proc/add_new_zlevel(name, traits = list(), z_type = /datum/space_level, contain_turfs = TRUE) + UNTIL(!adding_new_zlevel) + adding_new_zlevel = TRUE + var/new_z = z_list.len + 1 + if (world.maxz < new_z) + world.incrementMaxZ() + CHECK_TICK + // TODO: sleep here if the Z level needs to be cleared + var/datum/space_level/S = new z_type(new_z, name, traits) + manage_z_level(S, filled_with_space = TRUE, contain_turfs = contain_turfs) + generate_linkages_for_z_level(new_z) + adding_new_zlevel = FALSE + SEND_GLOBAL_SIGNAL(COMSIG_GLOB_NEW_Z, S) + return S + +/datum/controller/subsystem/mapping/proc/get_level(z) + if (z_list && z >= 1 && z <= z_list.len) + return z_list[z] + CRASH("Unmanaged z-level [z]! maxz = [world.maxz], z_list.len = [z_list ? z_list.len : "null"]") diff --git a/code/modules/maps/swapmaps.dm b/code/modules/mapping/swapmaps.dm similarity index 100% rename from code/modules/maps/swapmaps.dm rename to code/modules/mapping/swapmaps.dm diff --git a/code/modules/mining/drilling/drill.dm b/code/modules/mining/drilling/drill.dm index ed5bb32435a..350cbbb2864 100644 --- a/code/modules/mining/drilling/drill.dm +++ b/code/modules/mining/drilling/drill.dm @@ -109,7 +109,7 @@ attached_satchel.insert_into_storage(ore) else if(istype(get_turf(src), /turf/simulated/floor)) var/turf/simulated/floor/T = get_turf(src) - var/turf/below_turf = GetBelow(T) + var/turf/below_turf = GET_TURF_BELOW(T) if(below_turf && !istype(below_turf.loc, /area/mine) && !istype(below_turf.loc, /area/exoplanet) && !istype(below_turf.loc, /area/template_noop)) system_error("Potential station breach below.") return diff --git a/code/modules/mining/mine_items.dm b/code/modules/mining/mine_items.dm index a80ae41fa1f..388ebffbf10 100644 --- a/code/modules/mining/mine_items.dm +++ b/code/modules/mining/mine_items.dm @@ -1262,7 +1262,8 @@ var/list/total_extraction_beacons = list() return TRUE if("ladder") - var/turf/above = GET_ABOVE(src) + var/turf/T = get_turf(src) + var/turf/above = GET_TURF_ABOVE(T) if(!above) to_chat(user, SPAN_WARNING("There is nothing above you to make a ladder towards.")) return FALSE @@ -1278,7 +1279,8 @@ var/list/total_extraction_beacons = list() return TRUE return FALSE if("ladder") - var/turf/above = GET_ABOVE(src) + var/turf/T = get_turf(src) + var/turf/above = GET_TURF_ABOVE(T) if(!above) to_chat(user, SPAN_WARNING("There is nothing above you to make a ladder towards.")) return FALSE @@ -1323,7 +1325,8 @@ var/list/total_extraction_beacons = list() return TRUE if("ladder") - var/turf/above = GET_ABOVE(src) + var/turf/T = get_turf(src) + var/turf/above = GET_TURF_ABOVE(T) if(!above) to_chat(user, SPAN_WARNING("There is nothing above you to make a ladder towards.")) return FALSE diff --git a/code/modules/mining/mine_turfs.dm b/code/modules/mining/mine_turfs.dm index 8dbb0521978..e668b9a0d32 100644 --- a/code/modules/mining/mine_turfs.dm +++ b/code/modules/mining/mine_turfs.dm @@ -600,7 +600,8 @@ var/list/mineral_can_smooth_with = list( if(ishuman(user) && user.a_intent == I_GRAB) var/mob/living/carbon/human/H = user - var/turf/destination = GetAbove(H) + var/turf/T = get_turf(H) + var/turf/destination = GET_TURF_ABOVE(T) if(destination) var/turf/start = get_turf(H) if(start.CanZPass(H, UP)) @@ -816,7 +817,7 @@ var/list/asteroid_floor_smooth = list( if(digging) return if(dug) - if(!GetBelow(src)) + if(!GET_TURF_BELOW(src)) return to_chat(user, SPAN_NOTICE("You start digging deeper.")) playsound(get_turf(user), 'sound/effects/stonedoor_openclose.ogg', 50, TRUE) @@ -960,7 +961,7 @@ var/list/asteroid_floor_smooth = list( dug += 1 AddOverlays("asteroid_dug", TRUE) else - var/turf/below = GetBelow(src) + var/turf/below = GET_TURF_BELOW(src) if(below) var/area/below_area = get_area(below) // Let's just assume that the turf is not in nullspace. if(below_area.station_area) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 79c64be6ddd..b2cea63631f 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -2264,7 +2264,8 @@ reset_view(null) QDEL_NULL(z_eye) return - var/turf/above = GetAbove(src) + var/turf/T = get_turf(src) + var/turf/above = GET_TURF_ABOVE(T) if(TURF_IS_MIMICING(above)) z_eye = new /atom/movable/z_observer/z_up(src, src) visible_message(SPAN_NOTICE("[src] looks up."), SPAN_NOTICE("You look up.")) @@ -2285,14 +2286,14 @@ QDEL_NULL(z_eye) return var/turf/T = get_turf(src) - if(TURF_IS_MIMICING(T) && HasBelow(T.z)) + if(TURF_IS_MIMICING(T) && GET_TURF_BELOW(T)) z_eye = new /atom/movable/z_observer/z_down(src, src) visible_message(SPAN_NOTICE("[src] looks below."), SPAN_NOTICE("You look below.")) reset_view(z_eye) return else T = get_step(T, dir) - if(TURF_IS_MIMICING(T) && HasBelow(T.z)) + if(TURF_IS_MIMICING(T) && GET_TURF_BELOW(T)) z_eye = new /atom/movable/z_observer/z_down(src, src, TRUE) visible_message(SPAN_NOTICE("[src] leans over to look below."), SPAN_NOTICE("You lean over to look below.")) reset_view(z_eye) diff --git a/code/modules/mob/living/carbon/human/human_attackhand.dm b/code/modules/mob/living/carbon/human/human_attackhand.dm index abc20fedd43..fbf07012e17 100644 --- a/code/modules/mob/living/carbon/human/human_attackhand.dm +++ b/code/modules/mob/living/carbon/human/human_attackhand.dm @@ -395,7 +395,8 @@ else visible_message(SPAN_DANGER("[H] pushes [src] forward!"), SPAN_DANGER("[H] pushes you forward!")) apply_effect(5, WEAKEN) - forceMove(GetAbove(z_eye)) //We use GetAbove so people can't cheese it by turning their sprite. + var/turf/current_turf = get_turf(z_eye) + forceMove(GET_TURF_ABOVE(current_turf)) //We use GET_TURF_ABOVE so people can't cheese it by turning their sprite. return if(randn <= 25) diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm index 7dfc835c3f7..bf41dfd4b03 100644 --- a/code/modules/mob/living/carbon/human/human_movement.dm +++ b/code/modules/mob/living/carbon/human/human_movement.dm @@ -150,7 +150,7 @@ footsound = T.footstep_sound if (client) - var/turf/B = GetAbove(T) + var/turf/B = GET_TURF_ABOVE(T) if(up_hint) up_hint.icon_state = "uphint[(B ? !!B.is_hole : 0)]" diff --git a/code/modules/mob/living/maneuvers/maneuver_leap.dm b/code/modules/mob/living/maneuvers/maneuver_leap.dm index af5bd9c0095..7f2ce0ad877 100644 --- a/code/modules/mob/living/maneuvers/maneuver_leap.dm +++ b/code/modules/mob/living/maneuvers/maneuver_leap.dm @@ -27,11 +27,11 @@ var/turf/T = get_turf(target) var/damage_mod = 1 var/from_above = FALSE - if(H.can_fall(GET_BELOW(T))) + if(H.can_fall(GET_TURF_BELOW(T))) from_above = TRUE if(isopenspace(T)) while(isopenspace(T)) - T = GET_BELOW(T) + T = GET_TURF_BELOW(T) damage_mod += 1 if(isturf(T)) T.visible_message(SPAN_DANGER("[H] lands on \the [T] with a quake!")) diff --git a/code/modules/mob/living/silicon/robot/robot_movement.dm b/code/modules/mob/living/silicon/robot/robot_movement.dm index 4ac39b72bfe..458b2e63099 100644 --- a/code/modules/mob/living/silicon/robot/robot_movement.dm +++ b/code/modules/mob/living/silicon/robot/robot_movement.dm @@ -66,7 +66,8 @@ to_chat(cleaned_human, SPAN_WARNING("\The [src] runs its bottom mounted bristles all over you!")) if(client) - var/turf/B = GetAbove(get_turf(src)) + var/turf/T = get_turf(src) + var/turf/B = GET_TURF_ABOVE(T) if(up_hint) up_hint.icon_state = "uphint[(B ? !!B.is_hole : 0)]" diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index da79f56d247..ad3f9865fc8 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -1492,12 +1492,12 @@ if(!T.is_outside()) // For non-multiz we'll give everyone some nice ambience. - if(!HasAbove(T.z)) + if(!GET_TURF_ABOVE(T)) return WEATHER_ROOFED // For multi-z, check the actual weather on the turf above. // TODO: maybe make this a property of the z-level marker. - var/turf/above = GetAbove(T) + var/turf/above = GET_TURF_ABOVE(T) if(above.weather) return WEATHER_ROOFED diff --git a/code/modules/multiz/basic.dm b/code/modules/multiz/basic.dm index 2815e87838d..658295b7e33 100644 --- a/code/modules/multiz/basic.dm +++ b/code/modules/multiz/basic.dm @@ -1,6 +1,3 @@ -// If you add a more comprehensive system, just untick this file. -// Because this shit before was, for some reason, a bitfield. -GLOBAL_LIST_EMPTY(z_levels) var/list/list/connected_z_cache = list() // If the height is more than 1, we mark all contained levels as connected. @@ -10,43 +7,16 @@ var/list/list/connected_z_cache = list() return if(_height) height = _height - for(var/i = (loc.z - height + 1) to (loc.z-1)) - if (GLOB.z_levels.len = world.maxz || z < 1 || z > GLOB.z_levels.len) - return 0 - return GLOB.z_levels[z] - -/proc/HasBelow(var/z) - if(z > world.maxz || z < 2 || (z-1) > GLOB.z_levels.len) - return 0 - return GLOB.z_levels[z-1] - -// Thankfully, no bitwise magic is needed here. -/proc/GetAbove(var/atom/atom) - var/turf/turf = get_turf(atom) - if(!turf) - return null - return HasAbove(turf.z) ? get_step(turf, UP) : null - -/proc/GetBelow(var/atom/atom) - var/turf/turf = get_turf(atom) - if(!turf) - return null - return HasBelow(turf.z) ? get_step(turf, DOWN) : null - /proc/GetConnectedZlevels(z) . = list(z) - for(var/level = z, HasBelow(level), level--) + for(var/level = z, SSmapping.multiz_levels[level][Z_LEVEL_DOWN], level--) . |= level-1 - for(var/level = z, HasAbove(level), level++) + for(var/level = z, SSmapping.multiz_levels[level][Z_LEVEL_UP], level++) . |= level+1 /proc/AreConnectedZLevels(var/zA, var/zB) @@ -76,10 +46,11 @@ var/list/list/connected_z_cache = list() CRASH("Expected atom.") if (!ref.z) ref = get_turf(ref) + var/turf/T = get_turf(ref) switch (dir) if (UP) - . = GET_ABOVE(ref) + . = GET_TURF_ABOVE(T) if (DOWN) - . = GET_BELOW(ref) + . = GET_TURF_BELOW(T) else . = get_step(ref, dir) diff --git a/code/modules/multiz/disabled.dm b/code/modules/multiz/disabled.dm index 5c99bcb370c..39528a96d10 100644 --- a/code/modules/multiz/disabled.dm +++ b/code/modules/multiz/disabled.dm @@ -3,8 +3,3 @@ return 0 /proc/HasBelow(var/z) return 0 -// These give either the turf or null. -/proc/GetAbove(var/turf/turf) - return null -/proc/GetBelow(var/turf/turf) - return null diff --git a/code/modules/multiz/hoist.dm b/code/modules/multiz/hoist.dm index 3be6c80a379..3de543b829e 100644 --- a/code/modules/multiz/hoist.dm +++ b/code/modules/multiz/hoist.dm @@ -229,7 +229,8 @@ collapse_kit() /obj/structure/hoist/proc/can_move_dir(direction) - var/turf/dest = direction == UP ? GetAbove(source_hook) : GetBelow(source_hook) + var/turf/T = get_turf(source_hook) + var/turf/dest = direction == UP ? GET_TURF_ABOVE(T) : GET_TURF_BELOW(T) switch(direction) if (UP) if (!isopenturf(dest)) // can't move into a solid tile @@ -247,7 +248,8 @@ /obj/structure/hoist/proc/move_dir(direction) if (!can_move_dir(direction)) return FALSE - var/turf/move_dest = direction == UP ? GetAbove(source_hook) : GetBelow(source_hook) + var/turf/T = get_turf(source_hook) + var/turf/move_dest = direction == UP ? GET_TURF_ABOVE(T) : GET_TURF_BELOW(T) source_hook.forceMove(move_dest) if (hoistee) hoistee.hoist_act(move_dest) diff --git a/code/modules/multiz/mobile_ladders.dm b/code/modules/multiz/mobile_ladders.dm index c1eec5fd5c4..a6158748821 100644 --- a/code/modules/multiz/mobile_ladders.dm +++ b/code/modules/multiz/mobile_ladders.dm @@ -13,7 +13,8 @@ /obj/item/ladder_mobile/proc/place_ladder(atom/A, mob/user) if (isopenturf(A)) //Place into open space - var/turf/below_loc = GetBelow(A) + var/turf/T = get_turf(A) + var/turf/below_loc = GET_TURF_BELOW(T) if (!below_loc || (istype(/turf/space, below_loc))) to_chat(user, SPAN_NOTICE("Why would you do that?! There is only infinite space there...")) return @@ -32,7 +33,8 @@ qdel(src) else if (istype(A, /turf/simulated/floor) || istype(A, /turf/unsimulated/floor)) //Place onto Floor - var/turf/upper_loc = GetAbove(A) + var/turf/T = get_turf(A) + var/turf/upper_loc = GET_TURF_ABOVE(T) if (!upper_loc || !isopenturf(upper_loc)) to_chat(user, SPAN_NOTICE("There is something above. You can't deploy!")) return diff --git a/code/modules/multiz/movement.dm b/code/modules/multiz/movement.dm index 3b248f0d071..cb542b92fd6 100644 --- a/code/modules/multiz/movement.dm +++ b/code/modules/multiz/movement.dm @@ -40,7 +40,8 @@ to_chat(src, SPAN_WARNING("You lack means of travel in that direction.")) return FALSE - var/turf/destination = (direction == UP) ? GetAbove(src) : GetBelow(src) + var/turf/T = get_turf(src) + var/turf/destination = (direction == UP) ? GET_TURF_ABOVE(T) : GET_TURF_BELOW(T) if(!destination) to_chat(src, SPAN_NOTICE("There is nothing of interest in this direction.")) @@ -104,14 +105,16 @@ return ..() /mob/abstract/eye/zMove(direction) - var/turf/destination = (direction == UP) ? GetAbove(src) : GetBelow(src) + var/turf/T = get_turf(src) + var/turf/destination = (direction == UP) ? GET_TURF_ABOVE(T) : GET_TURF_BELOW(T) if(destination) setLoc(destination) else to_chat(owner, SPAN_NOTICE("There is nothing of interest in this direction.")) /mob/abstract/observer/zMove(direction) - var/turf/destination = (direction == UP) ? GetAbove(src) : GetBelow(src) + var/turf/T = get_turf(src) + var/turf/destination = (direction == UP) ? GET_TURF_ABOVE(T) : GET_TURF_BELOW(T) if(destination) forceMove(destination) else @@ -151,9 +154,9 @@ /mob/living/carbon/human/proc/climb(var/direction, var/turf/source, var/climb_bonus) var/turf/destination if(direction == UP) - destination = GetAbove(source) + destination = GET_TURF_ABOVE(source) else - destination = GetBelow(source) + destination = GET_TURF_BELOW(source) if(!destination) return diff --git a/code/modules/multiz/pipes.dm b/code/modules/multiz/pipes.dm index 4898212ff3d..5a1271ac783 100644 --- a/code/modules/multiz/pipes.dm +++ b/code/modules/multiz/pipes.dm @@ -167,7 +167,8 @@ node1 = target break - var/turf/above = GetAbove(src) + var/turf/current_turf = get_turf(src) + var/turf/above = GET_TURF_ABOVE(current_turf) if(above) for(var/obj/machinery/atmospherics/target in above) if(target.initialize_directions && istype(target, /obj/machinery/atmospherics/pipe/zpipe/down)) @@ -210,7 +211,8 @@ node1 = target break - var/turf/below = GetBelow(src) + var/turf/T = get_turf(src) + var/turf/below = GET_TURF_BELOW(T) if(below) for(var/obj/machinery/atmospherics/target in below) if(target.initialize_directions && istype(target, /obj/machinery/atmospherics/pipe/zpipe/up)) @@ -219,7 +221,6 @@ break - var/turf/T = src.loc // hide if turf is not intact hide(!T.is_plating()) //////////////////////////////// diff --git a/code/modules/multiz/structures.dm b/code/modules/multiz/structures.dm index 2267aace098..9ae11953e3e 100644 --- a/code/modules/multiz/structures.dm +++ b/code/modules/multiz/structures.dm @@ -34,7 +34,8 @@ . = ..() // the upper will connect to the lower if(allowed_directions & DOWN) //we only want to do the top one, as it will initialize the ones before it. - for(var/obj/structure/ladder/L in GetBelow(src)) + var/turf/T = get_turf(src) + for(var/obj/structure/ladder/L in GET_TURF_BELOW(T)) if(L.allowed_directions & UP) target_down = L L.target_up = src @@ -237,7 +238,7 @@ /obj/structure/stairs/Initialize() . = ..() for(var/turf/turf in locs) - var/turf/simulated/open/above = GetAbove(turf) + var/turf/simulated/open/above = GET_TURF_ABOVE(turf) if(!above) log_asset("Stair created without z-level above: ([loc.x], [loc.y], [loc.z])") return INITIALIZE_HINT_QDEL @@ -264,7 +265,8 @@ var/atom/movable/AM = bumped_atom // This is hackish but whatever. - var/turf/target = get_step(GetAbove(AM), dir) + var/turf/T = get_turf(AM) + var/turf/target = get_step(GET_TURF_ABOVE(T), dir) if(!target) return if(target.z > (z + 1)) //Prevents wheelchair fuckery. Basically, you teleport twice because both the wheelchair + your mob collide with the stairs. diff --git a/code/modules/multiz/turfs/open_space.dm b/code/modules/multiz/turfs/open_space.dm index 3f1db9825e1..ebb7a2a0ae5 100644 --- a/code/modules/multiz/turfs/open_space.dm +++ b/code/modules/multiz/turfs/open_space.dm @@ -181,7 +181,8 @@ * Updates the turf with open turf's variables and basically resets it properly. */ /turf/simulated/open/proc/update(mapload = FALSE) - below = GetBelow(src) + var/turf/T = get_turf(src) + below = GET_TURF_BELOW(T) // Edge case for when an open turf is above space on the lowest level. if (below) @@ -211,7 +212,8 @@ . = ..() if(distance <= 2) var/depth = 1 - for(var/T = GetBelow(src); isopenspace(T); T = GetBelow(T)) + var/turf/current_turf = get_turf(src) + for(var/turf/T = GET_TURF_BELOW(current_turf); isopenspace(T); T = GET_TURF_BELOW(T)) depth += 1 . += "It is about [depth] level\s deep." @@ -259,7 +261,8 @@ if(ishuman(user) && user.a_intent == I_GRAB) var/mob/living/carbon/human/H = user - var/turf/climbing_wall = GetBelow(H) + var/turf/T = get_turf(H) + var/turf/climbing_wall = GET_TURF_BELOW(T) var/climb_bonus = 0 if(istype(climbing_wall, /turf/simulated/mineral)) climb_bonus = 20 @@ -276,7 +279,7 @@ //Returns the roof type of the turf below /turf/simulated/open/get_roof_type() - var/turf/t = GetBelow(src) + var/turf/t = GET_TURF_BELOW(src) if(!t) return null return t.roof_type diff --git a/code/modules/multiz/zmimic/mimic_common.dm b/code/modules/multiz/zmimic/mimic_common.dm index e1064f635c8..34cf4a53ed4 100644 --- a/code/modules/multiz/zmimic/mimic_common.dm +++ b/code/modules/multiz/zmimic/mimic_common.dm @@ -3,9 +3,9 @@ return /turf/proc/is_above_space() - var/turf/T = GetBelow(src) + var/turf/T = GET_TURF_BELOW(src) while (T && (T.z_flags & ZM_MIMIC_BELOW)) - T = GetBelow(T) + T = GET_TURF_BELOW(T) return isspaceturf(T) /turf/update_icon() diff --git a/code/modules/multiz/zmimic/mimic_turf.dm b/code/modules/multiz/zmimic/mimic_turf.dm index f3e9f933927..5af399329cb 100644 --- a/code/modules/multiz/zmimic/mimic_turf.dm +++ b/code/modules/multiz/zmimic/mimic_turf.dm @@ -54,7 +54,7 @@ CRASH("Attempt to enable Z-mimic on already-enabled turf!") shadower = new(src) SSzcopy.openspace_turfs += 1 - var/turf/under = GetBelow(src) + var/turf/under = GET_TURF_BELOW(src) if (under) below = under below.above = src diff --git a/code/modules/overmap/exoplanets/exoplanet.dm b/code/modules/overmap/exoplanets/exoplanet.dm index 3b16898e966..460c0d2dc6f 100644 --- a/code/modules/overmap/exoplanets/exoplanet.dm +++ b/code/modules/overmap/exoplanets/exoplanet.dm @@ -149,9 +149,8 @@ planet_name = generate_planet_name() name = "[planet_name], \a [name]" - world.maxz++ - forceMove(locate(1,1,world.maxz)) - SEND_GLOBAL_SIGNAL(COMSIG_GLOB_NEW_Z, world.maxz) + var/datum/space_level/exoplanet_level = SSmapping.add_new_zlevel("Exoplanet [name]", ZTRAITS_AWAY, contain_turfs = FALSE) + forceMove(locate(1, 1, exoplanet_level.z_value)) pre_ruin_preparation() if(LAZYLEN(possible_themes)) diff --git a/code/modules/overmap/sectors.dm b/code/modules/overmap/sectors.dm index 928ed910848..208f43b93fd 100644 --- a/code/modules/overmap/sectors.dm +++ b/code/modules/overmap/sectors.dm @@ -283,13 +283,13 @@ var/global/area/overmap/map_overmap magnet_survey_result = "" /proc/build_overmap() + set waitfor = FALSE if(!SSatlas.current_map.use_overmap) return 1 log_module_sectors("Building overmap...") - world.maxz++ - SSatlas.current_map.overmap_z = world.maxz - SEND_GLOBAL_SIGNAL(COMSIG_GLOB_NEW_Z, world.maxz) + var/datum/space_level/overmap_spacelevel = SSmapping.add_new_zlevel("Overmap", ZTRAITS_OVERMAP, contain_turfs = FALSE) + SSatlas.current_map.overmap_z = overmap_spacelevel.z_value log_module_sectors("Putting overmap on [SSatlas.current_map.overmap_z]") var/area/overmap/A = new diff --git a/code/modules/overmap/ships/landable.dm b/code/modules/overmap/ships/landable.dm index 3b0327e901a..639c5b13c68 100644 --- a/code/modules/overmap/ships/landable.dm +++ b/code/modules/overmap/ships/landable.dm @@ -39,10 +39,9 @@ /obj/effect/overmap/visitable/ship/landable/find_z_levels() if(!use_mapped_z_levels) for(var/i = 0 to multiz) - world.maxz++ - map_z += world.maxz - SEND_GLOBAL_SIGNAL(COMSIG_GLOB_NEW_Z, world.maxz) - var/turf/center_loc = locate(round(world.maxx/2), round(world.maxy/2), world.maxz) + var/datum/space_level/S = SSmapping.add_new_zlevel("Landable Landmark [i] for [shuttle]", list(ZTRAIT_RESERVED = TRUE), contain_turfs = FALSE) + map_z += S.z_value + var/turf/center_loc = locate(round(world.maxx/2), round(world.maxy/2), map_z[length(map_z)]) landmark = new (center_loc, shuttle) add_landmark(landmark, shuttle) var/visitor_dir = fore_dir @@ -53,7 +52,7 @@ visitor_dir = turn(visitor_dir, 90) if(multiz) - new /obj/effect/landmark/map_data(locate(1, 1, world.maxz), (multiz + 1)) + new /obj/effect/landmark/map_data(locate(1, 1, map_z[length(map_z)]), (multiz + 1)) else ..() diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm index eebc7b43a24..2b55bae6770 100644 --- a/code/modules/power/cable.dm +++ b/code/modules/power/cable.dm @@ -180,7 +180,7 @@ By design, d1 is the smallest direction and d2 is the highest playsound(src.loc, 'sound/items/Wirecutter.ogg', 50, 1) if(d1 == 11 || d2 == 11) - var/turf/turf = GetBelow(src) + var/turf/turf = GET_TURF_BELOW(T) if(turf) for(var/obj/structure/cable/c in turf) if(c.d1 == 12 || c.d2 == 12) @@ -382,12 +382,14 @@ By design, d1 is the smallest direction and d2 is the highest // Handle up/down cables if(d1 == 11 || d2 == 11) - T = GetBelow(src) + var/turf/current_turf = get_turf(src) + T = GET_TURF_BELOW(current_turf) if(T) . += power_list(T, src, 12, powernetless_only) if(d1 == 12 || d2 == 12) - T = GetAbove(src) + var/turf/current_turf = get_turf(src) + T = GET_TURF_ABOVE(current_turf) if(T) . += power_list(T, src, 11, powernetless_only) @@ -792,7 +794,7 @@ By design, d1 is the smallest direction and d2 is the highest return var/obj/structure/cable/C = new(F) - var/obj/structure/cable/D = new(GetBelow(F)) + var/obj/structure/cable/D = new(GET_TURF_BELOW(F)) C.cableColor(color) diff --git a/code/modules/power/singularity/act.dm b/code/modules/power/singularity/act.dm index 39e8f741be7..bd3c9342638 100644 --- a/code/modules/power/singularity/act.dm +++ b/code/modules/power/singularity/act.dm @@ -108,12 +108,12 @@ if(O.invisibility == 101) O.singularity_act(src, current_size) if(go_up && current_size >= STAGE_FIVE) - if(HasAbove(src.z)) - var/turf/A = GetAbove(src) + if(GET_TURF_ABOVE(src)) + var/turf/A = GET_TURF_ABOVE(src) A.singularity_act(S, current_size, 0, 1) if(go_down && current_size >= STAGE_FIVE) - if(HasBelow(src.z)) - var/turf/B = GetBelow(src) + if(GET_TURF_BELOW(src)) + var/turf/B = GET_TURF_BELOW(src) B.singularity_act(S, current_size, 1, 0) if(istype(src,/turf/simulated/mineral)) var/turf/simulated/mineral/M = src diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm index d27874b981d..3444e04639b 100644 --- a/code/modules/power/singularity/singularity.dm +++ b/code/modules/power/singularity/singularity.dm @@ -507,7 +507,8 @@ return FALSE /obj/singularity/proc/zMove(direction) - var/turf/destination = (direction == UP) ? GetAbove(src) : GetBelow(src) + var/turf/T = get_turf(src) + var/turf/destination = (direction == UP) ? GET_TURF_ABOVE(T) : GET_TURF_BELOW(T) if(destination) forceMove(destination) diff --git a/code/modules/power/tesla/energy_ball.dm b/code/modules/power/tesla/energy_ball.dm index 044d91db76d..5a8a3acd0cb 100644 --- a/code/modules/power/tesla/energy_ball.dm +++ b/code/modules/power/tesla/energy_ball.dm @@ -106,10 +106,12 @@ var/turf/T switch(move_dir) if(UP) - T = GetAbove(src) + var/turf/current_turf = get_turf(src) + T = GET_TURF_ABOVE(current_turf) z_move = 1 if(DOWN) - T = GetBelow(src) + var/turf/current_turf = get_turf(src) + T = GET_TURF_BELOW(current_turf) z_move = -1 else T = get_step(src, move_dir) diff --git a/code/modules/random_map/automata/caves.dm b/code/modules/random_map/automata/caves.dm index e7422fa332c..400228aa3ba 100644 --- a/code/modules/random_map/automata/caves.dm +++ b/code/modules/random_map/automata/caves.dm @@ -129,7 +129,7 @@ if(EMPTY_CHAR) new_path = mineral_rich if(FLOOR_CHAR) - var/turf/below = GET_BELOW(T) + var/turf/below = GET_TURF_BELOW(T) if(below) var/area/below_area = below.loc // Let's just assume that the turf is not in nullspace. if(below_area.station_area) diff --git a/code/modules/recycling/disposal.dm b/code/modules/recycling/disposal.dm index 0b286777627..b06db263203 100644 --- a/code/modules/recycling/disposal.dm +++ b/code/modules/recycling/disposal.dm @@ -1084,7 +1084,8 @@ var/obj/structure/disposalpipe/P if(nextdir == 12) - T = GetAbove(src) + var/turf/current_turf = get_turf(src) + T = GET_TURF_ABOVE(current_turf) if(!T) H.forceMove(loc) return @@ -1133,7 +1134,8 @@ var/obj/structure/disposalpipe/P if(nextdir == 11) - T = GetBelow(src) + var/turf/current_turf = get_turf(src) + T = GET_TURF_BELOW(current_turf) if(!T) H.forceMove(src.loc) return diff --git a/code/modules/shieldgen/shield_gen.dm b/code/modules/shieldgen/shield_gen.dm index 82c75ec64ce..a786c345801 100644 --- a/code/modules/shieldgen/shield_gen.dm +++ b/code/modules/shieldgen/shield_gen.dm @@ -287,7 +287,7 @@ /obj/machinery/shield_gen/proc/getzabove(var/turf/location) var/connected = list() - var/turf/above = GetAbove(location) + var/turf/above = GET_TURF_ABOVE(location) if(above) connected += above @@ -299,7 +299,7 @@ /obj/machinery/shield_gen/proc/getzbelow(var/turf/location) var/connected = list() - var/turf/below = GetBelow(location) + var/turf/below = GET_TURF_BELOW(location) if(below) connected += below diff --git a/code/modules/shuttles/shuttle.dm b/code/modules/shuttles/shuttle.dm index d2c887ecd78..11ea2602e64 100644 --- a/code/modules/shuttles/shuttle.dm +++ b/code/modules/shuttles/shuttle.dm @@ -206,9 +206,10 @@ var/list/powernets = list() for(var/area/A in shuttle_area) // if there was a zlevel above our origin, erase our ceiling now we're leaving - if(HasAbove(current_location.z)) + var/turf/T = get_turf(current_location) + if(GET_TURF_ABOVE(T)) for(var/turf/TO in A.contents) - var/turf/TA = GetAbove(TO) + var/turf/TA = GET_TURF_ABOVE(TO) if(istype(TA, ceiling_type)) TA.ChangeTurf(get_base_turf_by_area(TA), 1, 1) if(knockdown) @@ -236,12 +237,13 @@ current_location = destination // if there's a zlevel above our destination, paint in a ceiling on it so we retain our air - if(HasAbove(current_location.z)) + var/turf/T = get_turf(current_location) + if(GET_TURF_ABOVE(T)) for(var/area/A in shuttle_area) for(var/turf/TD in A.contents) TD.update_above() TD.update_icon() - var/turf/TA = GetAbove(TD) + var/turf/TA = GET_TURF_ABOVE(TD) if(istype(TA, get_base_turf_by_area(TA)) || (istype(TA) && TA.is_open())) if(get_area(TA) in shuttle_area) continue diff --git a/code/modules/turbolift/turbolift.dm b/code/modules/turbolift/turbolift.dm index 2707e4ae0a6..f891d0e2721 100644 --- a/code/modules/turbolift/turbolift.dm +++ b/code/modules/turbolift/turbolift.dm @@ -98,7 +98,7 @@ AM.crush_act() else for(var/turf/simulated/wall/W in origin) - var/turf/T = GET_ABOVE(W) + var/turf/T = GET_TURF_ABOVE(W) for(var/atom/movable/AM in T) if(next_floor == floors[floors.len]) AM.crush_act() @@ -108,7 +108,9 @@ origin.move_contents_to(destination) for(var/thing in move_candidates) var/atom/movable/AM = thing - AM.forceMove(GET_ABOVE(AM)) + var/turf/T = get_turf(AM) + if(istype(T)) + AM.forceMove(GET_TURF_ABOVE(T)) current_floor = next_floor control_panel_interior.visible_message("The elevator [moving_upwards ? "rises" : "descends"] smoothly.") diff --git a/code/modules/vehicles/droppod.dm b/code/modules/vehicles/droppod.dm index a28f290636e..8e96cc8a64e 100644 --- a/code/modules/vehicles/droppod.dm +++ b/code/modules/vehicles/droppod.dm @@ -268,7 +268,7 @@ blastdoor_interact(TRUE) return - var/turf/aboveturf = GetAbove(A) + var/turf/aboveturf = GET_TURF_ABOVE(A) if(aboveturf) applyfalldamage(aboveturf) aboveturf.ChangeTurf(/turf/simulated/floor/foamedmetal) @@ -287,7 +287,7 @@ set_light(5,1,LIGHT_COLOR_EMERGENCY_SOFT) A.visible_message(SPAN_DANGER("\The [src] crashes through the roof!")) - var/turf/belowturf = GetBelow(A) + var/turf/belowturf = GET_TURF_BELOW(A) if(belowturf) belowturf.visible_message(SPAN_DANGER("You hear something crash into the ceiling above!")) status = USED diff --git a/code/modules/weather/weather_debug.dm b/code/modules/weather/weather_debug.dm index 45a521051ec..355e8efb08e 100644 --- a/code/modules/weather/weather_debug.dm +++ b/code/modules/weather/weather_debug.dm @@ -28,8 +28,8 @@ return var/turf/T = get_turf(usr) - while(T && HasAbove(T.z)) - T = GetAbove(T) + while(T && GET_TURF_ABOVE(T)) + T = GET_TURF_ABOVE(T) if(!istype(T)) to_chat(usr, SPAN_WARNING("You need to have a turf to use this verb.")) return diff --git a/code/modules/weather/weather_init.dm b/code/modules/weather/weather_init.dm index fc34dff97bd..915a68c7675 100644 --- a/code/modules/weather/weather_init.dm +++ b/code/modules/weather/weather_init.dm @@ -28,7 +28,7 @@ INITIALIZE_IMMEDIATE(/obj/abstract/weather_system) // Track all z-levels. for(var/highest_z in affecting_zs) var/turfcount = 0 - if(HasAbove(highest_z)) + if(SSmapping.multiz_levels[highest_z][Z_LEVEL_UP]) continue // Update turf weather. for(var/turf/T as anything in block(locate(1, 1, highest_z), locate(world.maxx, world.maxy, highest_z))) diff --git a/code/unit_tests/create_and_destroy.dm b/code/unit_tests/create_and_destroy.dm index c11b01a6270..d6413afe3fd 100644 --- a/code/unit_tests/create_and_destroy.dm +++ b/code/unit_tests/create_and_destroy.dm @@ -104,6 +104,9 @@ GLOBAL_VAR_INIT(running_create_and_destroy, FALSE) //Requires an owner or stacktrace on creation /atom/movable/flick_visual, + //Weather system, requires a z level + /obj/abstract/weather_system + ) // Paths and all the subpaths excluded diff --git a/code/unit_tests/map_tests.dm b/code/unit_tests/map_tests.dm index 694deb6d1dd..94921a76368 100644 --- a/code/unit_tests/map_tests.dm +++ b/code/unit_tests/map_tests.dm @@ -108,35 +108,6 @@ return 1 - -/datum/unit_test/map_test/roof_test - name = "MAP: Roof Test (Station)" - -/datum/unit_test/map_test/roof_test/start_test() - var/bad_tiles = 0 - var/tiles_total = 0 - var/turf/above - var/area/A - var/thing - for (thing in GLOB.the_station_areas) - A = thing - - for (var/turf/T in A) // Areas don't just contain turfs, so typed loop it is. - T = thing - tiles_total++ - above = GetAbove(T) - - if (above && above.is_hole) - bad_tiles++ - TEST_FAIL("[T.name] \[[T.x] / [T.y] / [T.z]\] Has no roof.") - - if (bad_tiles) - TEST_FAIL("\[[bad_tiles] / [tiles_total]\] station turfs had no roof.") - else - TEST_PASS("All \[[tiles_total]\] station turfs had a roof.") - - return 1 - #define BLOCKED_UP 1 #define BLOCKED_DOWN 2 @@ -160,7 +131,8 @@ continue var/bad = 0 - if (ladder.target_up && !isopenturf(GetAbove(ladder))) + var/turf/T = get_turf(ladder) + if (ladder.target_up && !isopenturf(GET_TURF_ABOVE(T))) bad |= BLOCKED_UP if (ladder.target_down && !isopenturf(ladder.loc)) diff --git a/html/changelogs/fluffyghost-zlevelmanager.yml b/html/changelogs/fluffyghost-zlevelmanager.yml new file mode 100644 index 00000000000..b96d65ffa94 --- /dev/null +++ b/html/changelogs/fluffyghost-zlevelmanager.yml @@ -0,0 +1,58 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# - (fixes bugs) +# wip +# - (work in progress) +# qol +# - (quality of life) +# soundadd +# - (adds a sound) +# sounddel +# - (removes a sound) +# rscadd +# - (adds a feature) +# rscdel +# - (removes a feature) +# imageadd +# - (adds an image or sprite) +# imagedel +# - (removes an image or sprite) +# spellcheck +# - (fixes spelling or grammar) +# experiment +# - (experimental change) +# balance +# - (balance changes) +# code_imp +# - (misc internal code change) +# refactor +# - (refactors code) +# config +# - (makes a change to the config files) +# admin +# - (makes changes to administrator tools) +# server +# - (miscellaneous changes to server) +################################# + +# Your name. +author: FluffyGhost + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, this gets changed to [] after reading. Just remove the brackets when you add new shit. +# Please surround your changes in double quotes ("). It works without them, but if you use certain characters it screws up compiling. The quotes will not show up in the changelog. +changes: + - rscadd: "Added the z-level manager system from TG, mostly." diff --git a/maps/_common/mapsystem/map.dm b/maps/_common/mapsystem/map.dm index 2d1f1d0b69b..db2da9f0ee4 100644 --- a/maps/_common/mapsystem/map.dm +++ b/maps/_common/mapsystem/map.dm @@ -164,9 +164,8 @@ /datum/map/proc/get_empty_zlevel() if(empty_levels == null) - world.maxz++ - empty_levels = list(world.maxz) - SEND_GLOBAL_SIGNAL(COMSIG_GLOB_NEW_Z, world.maxz) + var/datum/space_level/empty_level = SSmapping.add_new_zlevel("Empty Level", ZTRAITS_AWAY, contain_turfs = FALSE) + empty_levels = list(empty_level.z_value) return pick(empty_levels) /datum/map/proc/setup_shuttles() diff --git a/maps/away/away_site/blueriver/blueriver.dm b/maps/away/away_site/blueriver/blueriver.dm index a859f8a26be..0ca246989aa 100644 --- a/maps/away/away_site/blueriver/blueriver.dm +++ b/maps/away/away_site/blueriver/blueriver.dm @@ -8,7 +8,6 @@ prefix = "away_site/blueriver/" suffixes = list("blueriver-1.dmm","blueriver-2.dmm") - generate_mining_by_z = 2 sectors = list(SECTOR_ROMANOVICH, SECTOR_CORP_ZONE, SECTOR_VALLEY_HALE, SECTOR_BADLANDS, ALL_COALITION_SECTORS) sectors_blacklist = list(ALL_SPECIFIC_SECTORS) //it's a whole ass planet, shouldn't have it in predefined sectors diff --git a/maps/away/away_sites.dm b/maps/away/away_sites.dm index 490f0b0ca33..1f5234d2c1a 100644 --- a/maps/away/away_sites.dm +++ b/maps/away/away_sites.dm @@ -1,7 +1,6 @@ // Hey! Listen! Update \config\away_site_blacklist.txt with your new ruins! /datum/map_template/ruin/away_site - var/list/generate_mining_by_z prefix = "maps/away/" /// If null, ignored, and exoplanet generation is not used.