diff --git a/code/__HELPERS/_lists.dm b/code/__HELPERS/_lists.dm index 361bd10f329..7af30c8d972 100644 --- a/code/__HELPERS/_lists.dm +++ b/code/__HELPERS/_lists.dm @@ -97,6 +97,19 @@ LAZYINITLIST(lazy_list[key]); \ lazy_list[key] |= value; +///Ensures the length of a list is at least I, prefilling it with V if needed. if V is a proc call, it is repeated for each new index so that list() can just make a new list for each item. +#define LISTASSERTLEN(L, I, V...) \ + if (length(L) < I) { \ + var/_OLD_LENGTH = length(L); \ + L.len = I; \ + /* Convert the optional argument to a if check */ \ + for (var/_USELESS_VAR in list(V)) { \ + for (var/_INDEX_TO_ASSIGN_TO in _OLD_LENGTH+1 to I) { \ + L[_INDEX_TO_ASSIGN_TO] = V; \ + } \ + } \ + } + #define reverseList(L) reverse_range(L.Copy()) /// Passed into BINARY_INSERT to compare keys diff --git a/code/__HELPERS/areas.dm b/code/__HELPERS/areas.dm index dec768a6a0c..8df182c90d0 100644 --- a/code/__HELPERS/areas.dm +++ b/code/__HELPERS/areas.dm @@ -273,13 +273,11 @@ GLOBAL_LIST_INIT(typecache_powerfailure_safe_areas, typecacheof(list( // Now their turfs var/list/turfs = list() for(var/area/pull_from as anything in areas_to_pull) - var/list/our_turfs = pull_from.get_contained_turfs() - if(target_z == 0) - turfs += our_turfs + if (target_z == 0) + for (var/list/zlevel_turfs as anything in pull_from.get_zlevel_turf_lists()) + turfs += zlevel_turfs else - for(var/turf/turf_in_area as anything in our_turfs) - if(target_z == turf_in_area.z) - turfs += turf_in_area + turfs += pull_from.get_turfs_by_zlevel(target_z) return turfs diff --git a/code/controllers/subsystem/area_contents.dm b/code/controllers/subsystem/area_contents.dm index 904714f0ba0..054de9d8efc 100644 --- a/code/controllers/subsystem/area_contents.dm +++ b/code/controllers/subsystem/area_contents.dm @@ -1,4 +1,4 @@ -#define ALLOWED_LOOSE_TURFS 500 +#define ALLOWED_LOOSE_TURFS 100 /** * Responsible for managing the sizes of area.contained_turfs and area.turfs_to_uncontain * These lists do not check for duplicates, which is fine, but it also means they can balloon in size over time @@ -17,8 +17,11 @@ SUBSYSTEM_DEF(area_contents) var/total_clearing_from = 0 var/total_to_clear = 0 for(var/area/to_clear as anything in marked_for_clearing) - total_to_clear += length(to_clear.turfs_to_uncontain) - total_clearing_from += length(to_clear.contained_turfs) + for (var/area_zlevel in 1 to length(to_clear.turfs_to_uncontain_by_zlevel)) + if (length(to_clear.turfs_to_uncontain_by_zlevel[area_zlevel])) + total_to_clear += length(to_clear.turfs_to_uncontain_by_zlevel[area_zlevel]) + if (length(to_clear.turfs_by_zlevel) >= area_zlevel) //this should always be true, but stat_entry is no place for runtimes. fire() can handle that + total_clearing_from += length(to_clear.turfs_by_zlevel[area_zlevel]) msg = "A:[length(currentrun)] MR:[length(marked_for_clearing)] TC:[total_to_clear] CF:[total_clearing_from]" return ..() @@ -29,8 +32,10 @@ SUBSYSTEM_DEF(area_contents) while(length(currentrun)) var/area/test = currentrun[length(currentrun)] - if(length(test.turfs_to_uncontain) > ALLOWED_LOOSE_TURFS) - marked_for_clearing |= test + for (var/area_zlevel in 1 to length(test.turfs_to_uncontain_by_zlevel)) + if(length(test.turfs_to_uncontain_by_zlevel[area_zlevel]) > ALLOWED_LOOSE_TURFS) + marked_for_clearing |= test + break currentrun.len-- if(MC_TICK_CHECK) return @@ -39,19 +44,27 @@ SUBSYSTEM_DEF(area_contents) while(length(marked_for_clearing)) var/area/clear = marked_for_clearing[length(marked_for_clearing)] - // The operation of cutting large lists can be expensive - // It scales almost directly with the size of the list we're cutting with - // Because of this, we're gonna stick to cutting 1 entry at a time - // There's no reason to batch it I promise, this is faster. No overtime too - var/amount_cut = 0 - var/list/cut_from = clear.turfs_to_uncontain - for(amount_cut in 1 to length(cut_from)) - clear.contained_turfs -= cut_from[amount_cut] - if(MC_TICK_CHECK) - cut_from.Cut(1, amount_cut + 1) - return - - clear.turfs_to_uncontain = list() + for (var/area_zlevel in 1 to length(clear.turfs_to_uncontain_by_zlevel)) + if (!length(clear.turfs_to_uncontain_by_zlevel[area_zlevel])) + continue + if (length(clear.turfs_by_zlevel) < area_zlevel) + stack_trace("[clear]([clear.type])'s turfs_by_zlevel is length [length(clear.turfs_by_zlevel)] but we are being asked to remove turfs from zlevel [area_zlevel] from it.") + clear.turfs_to_uncontain_by_zlevel[area_zlevel] = list() + continue + + // The operation of cutting large lists can be expensive + // It scales almost directly with the size of the list we're cutting with + // Because of this, we're gonna stick to cutting 1 entry at a time + // There's no reason to batch it I promise, this is faster. No overtime too + var/amount_cut = 0 + var/list/cut_from = clear.turfs_to_uncontain_by_zlevel[area_zlevel] + for(amount_cut in 1 to length(cut_from)) + clear.turfs_by_zlevel[area_zlevel] -= cut_from[amount_cut] + if(MC_TICK_CHECK) + cut_from.Cut(1, amount_cut + 1) + return + + clear.turfs_to_uncontain_by_zlevel = list() marked_for_clearing.len-- #undef ALLOWED_LOOSE_TURFS diff --git a/code/controllers/subsystem/job.dm b/code/controllers/subsystem/job.dm index 38ef544e04c..4a8345728e5 100644 --- a/code/controllers/subsystem/job.dm +++ b/code/controllers/subsystem/job.dm @@ -714,13 +714,14 @@ SUBSYSTEM_DEF(job) var/area/shuttle/arrival/arrivals_area = GLOB.areas_by_type[/area/shuttle/arrival] if(!isnull(arrivals_area)) var/list/turf/available_turfs = list() - for(var/turf/arrivals_turf as anything in arrivals_area.get_contained_turfs()) - var/obj/structure/chair/shuttle_chair = locate() in arrivals_turf - if(!isnull(shuttle_chair)) - return shuttle_chair - if(arrivals_turf.is_blocked_turf(TRUE)) - continue - available_turfs += arrivals_turf + for (var/list/zlevel_turfs as anything in arrivals_area.get_zlevel_turf_lists()) + for (var/turf/arrivals_turf as anything in zlevel_turfs) + var/obj/structure/chair/shuttle_chair = locate() in arrivals_turf + if(!isnull(shuttle_chair)) + return shuttle_chair + if(arrivals_turf.is_blocked_turf(TRUE)) + continue + available_turfs += arrivals_turf if(length(available_turfs)) return pick(available_turfs) diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm index 5881405da0b..986a4c1bc8d 100644 --- a/code/controllers/subsystem/mapping.dm +++ b/code/controllers/subsystem/mapping.dm @@ -173,7 +173,7 @@ SUBSYSTEM_DEF(mapping) // Cache for sonic speed var/list/unused_turfs = src.unused_turfs var/list/world_contents = GLOB.areas_by_type[world.area].contents - var/list/world_turf_contents = GLOB.areas_by_type[world.area].contained_turfs + var/list/world_turf_contents_by_z = GLOB.areas_by_type[world.area].turfs_by_zlevel var/list/lists_to_reserve = src.lists_to_reserve var/index = 0 while(index < length(lists_to_reserve)) @@ -189,10 +189,12 @@ SUBSYSTEM_DEF(mapping) LAZYINITLIST(unused_turfs["[T.z]"]) unused_turfs["[T.z]"] |= T var/area/old_area = T.loc - old_area.turfs_to_uncontain += T + LISTASSERTLEN(old_area.turfs_to_uncontain_by_zlevel, T.z, list()) + old_area.turfs_to_uncontain_by_zlevel[T.z] += T T.turf_flags = UNUSED_RESERVATION_TURF world_contents += T - world_turf_contents += T + LISTASSERTLEN(world_turf_contents_by_z, T.z, list()) + world_turf_contents_by_z[T.z] += T packet.len-- packetlen = length(packet) @@ -835,12 +837,14 @@ GLOBAL_LIST_EMPTY(the_station_areas) // Faster if(space_guaranteed) var/area/global_area = GLOB.areas_by_type[world.area] - global_area.contained_turfs += Z_TURFS(z_level) + LISTASSERTLEN(global_area.turfs_by_zlevel, z_level, list()) + global_area.turfs_by_zlevel[z_level] = Z_TURFS(z_level) return for(var/turf/to_contain as anything in Z_TURFS(z_level)) var/area/our_area = to_contain.loc - our_area.contained_turfs += to_contain + LISTASSERTLEN(our_area.turfs_by_zlevel, z_level, list()) + our_area.turfs_by_zlevel[z_level] += to_contain /datum/controller/subsystem/mapping/proc/update_plane_tracking(datum/space_level/update_with) // We're essentially going to walk down the stack of connected z levels, and set their plane offset as we go diff --git a/code/controllers/subsystem/radioactive_nebula.dm b/code/controllers/subsystem/radioactive_nebula.dm index 3b11a7870af..17c0cc9b3da 100644 --- a/code/controllers/subsystem/radioactive_nebula.dm +++ b/code/controllers/subsystem/radioactive_nebula.dm @@ -50,9 +50,10 @@ SUBSYSTEM_DEF(radioactive_nebula) /// Loop through radioactive space (with lag checks) and make it all radioactive! /datum/controller/subsystem/radioactive_nebula/proc/irradiate_everything() for (var/area/area as anything in get_areas(radioactive_nebula.radioactive_areas)) - for (var/turf/turf as anything in area.get_contained_turfs()) - for (var/atom/movable/target as anything in turf) - fake_irradiate(target) + for (var/list/zlevel_turfs as anything in area.get_zlevel_turf_lists()) + for (var/turf/area_turf as anything in zlevel_turfs) + for (var/atom/movable/target as anything in area_turf) + fake_irradiate(target) CHECK_TICK diff --git a/code/controllers/subsystem/shuttle.dm b/code/controllers/subsystem/shuttle.dm index bb88e8d6824..ce7645529cb 100644 --- a/code/controllers/subsystem/shuttle.dm +++ b/code/controllers/subsystem/shuttle.dm @@ -645,7 +645,7 @@ SUBSYSTEM_DEF(shuttle) var/datum/turf_reservation/proposal = SSmapping.request_turf_block_reservation( transit_width, transit_height, - 1, + z_size = 1, //if this is changed the turf uncontain code below has to be updated to support multiple zs reservation_type = /datum/turf_reservation/transit, turf_type_override = transit_path, ) @@ -679,17 +679,22 @@ SUBSYSTEM_DEF(shuttle) if(!midpoint) qdel(proposal) return FALSE + var/area/old_area = midpoint.loc - old_area.turfs_to_uncontain += proposal.reserved_turfs - var/area/shuttle/transit/A = new() - A.parallax_movedir = travel_dir - A.contents = proposal.reserved_turfs - A.contained_turfs = proposal.reserved_turfs + LISTASSERTLEN(old_area.turfs_to_uncontain_by_zlevel, bottomleft.z, list()) + old_area.turfs_to_uncontain_by_zlevel[bottomleft.z] += proposal.reserved_turfs + + var/area/shuttle/transit/new_area = new() + new_area.parallax_movedir = travel_dir + new_area.contents = proposal.reserved_turfs + LISTASSERTLEN(new_area.turfs_by_zlevel, bottomleft.z, list()) + new_area.turfs_by_zlevel[bottomleft.z] = proposal.reserved_turfs + var/obj/docking_port/stationary/transit/new_transit_dock = new(midpoint) new_transit_dock.reserved_area = proposal new_transit_dock.name = "Transit for [M.shuttle_id]/[M.name]" new_transit_dock.owner = M - new_transit_dock.assigned_area = A + new_transit_dock.assigned_area = new_area // Add 180, because ports point inwards, rather than outwards new_transit_dock.setDir(angle2dir(dock_angle)) diff --git a/code/datums/achievements/misc_achievements.dm b/code/datums/achievements/misc_achievements.dm index 3a62e6c940a..231ab8aaabc 100644 --- a/code/datums/achievements/misc_achievements.dm +++ b/code/datums/achievements/misc_achievements.dm @@ -68,6 +68,7 @@ name = "One Lean, Mean, Cleaning Machine" desc = "How does it feel to know that your workplace values a mop bucket on wheels more than you?" // i can do better than this give me time database_id = MEDAL_CLEANBOSS + icon = "cleanboss" /datum/award/achievement/misc/rule8 name = "Rule 8" diff --git a/code/datums/station_traits/negative_traits.dm b/code/datums/station_traits/negative_traits.dm index 7b0ecf5b097..87e521b9533 100644 --- a/code/datums/station_traits/negative_traits.dm +++ b/code/datums/station_traits/negative_traits.dm @@ -381,69 +381,69 @@ /datum/station_trait/revolutionary_trashing/proc/trash_this_place() for(var/area/station/command/area_to_trash in GLOB.areas) - - for(var/turf/current_turf as anything in area_to_trash.get_contained_turfs()) - if(isclosedturf(current_turf)) - continue - if(prob(25)) - var/obj/effect/decal/cleanable/crayon/created_art - created_art = new(current_turf, RANDOM_COLOUR, pick(trash_talk)) - created_art.pixel_x = rand(-10, 10) - created_art.pixel_y = rand(-10, 10) - - if(prob(0.01)) - new /obj/effect/mob_spawn/corpse/human/assistant(current_turf) - continue - - for(var/atom/current_thing as anything in current_turf.contents) - if(istype(current_thing, /obj/machinery/light) && prob(40)) - var/obj/machinery/light/light_to_smash = current_thing - light_to_smash.break_light_tube(skip_sound_and_sparks = TRUE) - continue - - if(istype(current_thing, /obj/structure/window)) - if(prob(15)) - current_thing.take_damage(rand(30, 90)) - continue - - if(istype(current_thing, /obj/structure/table) && prob(40)) - current_thing.take_damage(100) - continue - - if(istype(current_thing, /obj/structure/chair) && prob(60)) - current_thing.take_damage(150) - continue - - if(istype(current_thing, /obj/machinery/computer) && prob(30)) - if(istype(current_thing, /obj/machinery/computer/communications)) - continue //To prevent the shuttle from getting autocalled at the start of the round - current_thing.take_damage(160) + for (var/list/zlevel_turfs as anything in area_to_trash.get_zlevel_turf_lists()) + for (var/turf/current_turf as anything in zlevel_turfs) + if(isclosedturf(current_turf)) continue - - if(istype(current_thing, /obj/machinery/vending) && prob(45)) - var/obj/machinery/vending/vendor_to_trash = current_thing - if(prob(50)) - vendor_to_trash.tilt(get_turf(vendor_to_trash), 0) // crit effects can do some real weird shit, lets disable it - - if(prob(50)) - vendor_to_trash.take_damage(150) - continue - - if(istype(current_thing, /obj/structure/fireaxecabinet)) //A staple of revolutionary behavior - current_thing.take_damage(90) - continue - - if(istype(current_thing, /obj/item/bedsheet/captain)) - new /obj/item/bedsheet/rev(current_thing.loc) - qdel(current_thing) - continue - - if(istype(current_thing, /obj/item/bedsheet/captain/double)) - new /obj/item/bedsheet/rev/double(current_thing.loc) - qdel(current_thing) + if(prob(25)) + var/obj/effect/decal/cleanable/crayon/created_art + created_art = new(current_turf, RANDOM_COLOUR, pick(trash_talk)) + created_art.pixel_x = rand(-10, 10) + created_art.pixel_y = rand(-10, 10) + + if(prob(0.01)) + new /obj/effect/mob_spawn/corpse/human/assistant(current_turf) continue - CHECK_TICK + for(var/atom/current_thing as anything in current_turf.contents) + if(istype(current_thing, /obj/machinery/light) && prob(40)) + var/obj/machinery/light/light_to_smash = current_thing + light_to_smash.break_light_tube(skip_sound_and_sparks = TRUE) + continue + + if(istype(current_thing, /obj/structure/window)) + if(prob(15)) + current_thing.take_damage(rand(30, 90)) + continue + + if(istype(current_thing, /obj/structure/table) && prob(40)) + current_thing.take_damage(100) + continue + + if(istype(current_thing, /obj/structure/chair) && prob(60)) + current_thing.take_damage(150) + continue + + if(istype(current_thing, /obj/machinery/computer) && prob(30)) + if(istype(current_thing, /obj/machinery/computer/communications)) + continue //To prevent the shuttle from getting autocalled at the start of the round + current_thing.take_damage(160) + continue + + if(istype(current_thing, /obj/machinery/vending) && prob(45)) + var/obj/machinery/vending/vendor_to_trash = current_thing + if(prob(50)) + vendor_to_trash.tilt(get_turf(vendor_to_trash), 0) // crit effects can do some real weird shit, lets disable it + + if(prob(50)) + vendor_to_trash.take_damage(150) + continue + + if(istype(current_thing, /obj/structure/fireaxecabinet)) //A staple of revolutionary behavior + current_thing.take_damage(90) + continue + + if(istype(current_thing, /obj/item/bedsheet/captain)) + new /obj/item/bedsheet/rev(current_thing.loc) + qdel(current_thing) + continue + + if(istype(current_thing, /obj/item/bedsheet/captain/double)) + new /obj/item/bedsheet/rev/double(current_thing.loc) + qdel(current_thing) + continue + + CHECK_TICK ///Station traits that influence the space background and apply some unique effects! /datum/station_trait/nebula diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index e6002412339..46ee3669b83 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -13,14 +13,16 @@ mouse_opacity = MOUSE_OPACITY_TRANSPARENT invisibility = INVISIBILITY_LIGHTING - /// List of all turfs currently inside this area. Acts as a filtered bersion of area.contents - /// For faster lookup (area.contents is actually a filtered loop over world) + /// List of all turfs currently inside this area as nested lists indexed by zlevel. + /// Acts as a filtered bersion of area.contents For faster lookup + /// (area.contents is actually a filtered loop over world) /// Semi fragile, but it prevents stupid so I think it's worth it - var/list/turf/contained_turfs = list() - /// Contained turfs is a MASSIVE list, so rather then adding/removing from it each time we have a problem turf + var/list/list/turf/turfs_by_zlevel = list() + /// turfs_by_z_level can become MASSIVE lists, so rather then adding/removing from it each time we have a problem turf /// We should instead store a list of turfs to REMOVE from it, then hook into a getter for it /// There is a risk of this and contained_turfs leaking, so a subsystem will run it down to 0 incrementally if it gets too large - var/list/turf/turfs_to_uncontain = list() + /// This uses the same nested list format as turfs_by_zlevel + var/list/list/turf/turfs_to_uncontain_by_zlevel = list() var/area_flags = VALID_TERRITORY | BLOBS_ALLOWED | UNIQUE_AREA | CULT_PERMITTED @@ -224,24 +226,93 @@ GLOBAL_LIST_EMPTY(teleportlocs) turfs += T map_generator.generate_terrain(turfs, src) -/area/proc/get_contained_turfs() - if(length(turfs_to_uncontain)) +/// Returns the highest zlevel that this area contains turfs for +/area/proc/get_highest_zlevel() + for (var/area_zlevel in length(turfs_by_zlevel) to 1 step -1) + if (length(turfs_to_uncontain_by_zlevel) >= area_zlevel) + if (length(turfs_by_zlevel[area_zlevel]) - length(turfs_to_uncontain_by_zlevel[area_zlevel]) > 0) + return area_zlevel + else + if (length(turfs_by_zlevel[area_zlevel])) + return area_zlevel + return 0 + +/// Returns a nested list of lists with all turfs split by zlevel. +/// only zlevels with turfs are returned. The order of the list is not guaranteed. +/area/proc/get_zlevel_turf_lists() + if(length(turfs_to_uncontain_by_zlevel)) cannonize_contained_turfs() - return contained_turfs + + var/list/zlevel_turf_lists = list() + + for (var/list/zlevel_turfs as anything in turfs_by_zlevel) + if (length(zlevel_turfs)) + zlevel_turf_lists[++zlevel_turf_lists.len] = zlevel_turfs + + return zlevel_turf_lists + +/// Returns a list with all turfs in this zlevel. +/area/proc/get_turfs_by_zlevel(zlevel) + if (length(turfs_to_uncontain_by_zlevel) >= zlevel && length(turfs_to_uncontain_by_zlevel[zlevel])) + cannonize_contained_turfs_by_zlevel(zlevel) + + if (length(turfs_by_zlevel) < zlevel) + return list() + + return turfs_by_zlevel[zlevel] + + +/// Merges a list containing all of the turfs zlevel lists from get_zlevel_turf_lists inside one list. Use get_zlevel_turf_lists() or get_turfs_by_zlevel() unless you need all the turfs in one list to avoid generating large lists +/area/proc/get_turfs_from_all_zlevels() + . = list() + for (var/list/zlevel_turfs as anything in get_zlevel_turf_lists()) + . += zlevel_turfs /// Ensures that the contained_turfs list properly represents the turfs actually inside us -/area/proc/cannonize_contained_turfs() +/area/proc/cannonize_contained_turfs_by_zlevel(zlevel_to_clean, _autoclean = TRUE) // This is massively suboptimal for LARGE removal lists // Try and keep the mass removal as low as you can. We'll do this by ensuring // We only actually add to contained turfs after large changes (Also the management subsystem) // Do your damndest to keep turfs out of /area/space as a stepping stone - // That sucker gets HUGE and will make this take actual tens of seconds if you stuff turfs_to_uncontain - contained_turfs -= turfs_to_uncontain - turfs_to_uncontain = list() + // That sucker gets HUGE and will make this take actual seconds + if (zlevel_to_clean <= length(turfs_by_zlevel) && zlevel_to_clean <= length(turfs_to_uncontain_by_zlevel)) + turfs_by_zlevel[zlevel_to_clean] -= turfs_to_uncontain_by_zlevel[zlevel_to_clean] + + if (_autoclean) // Removes empty lists from the end of this list + var/new_length = length(turfs_to_uncontain_by_zlevel) + // Walk backwards thru the list + for (var/i in length(turfs_to_uncontain_by_zlevel) to 0 step -1) + if (i && length(turfs_to_uncontain_by_zlevel[i])) + break // Stop the moment we find a useful list + new_length = i + + if (new_length < length(turfs_to_uncontain_by_zlevel)) + turfs_to_uncontain_by_zlevel.len = new_length + + if (new_length >= zlevel_to_clean) + turfs_to_uncontain_by_zlevel[zlevel_to_clean] = list() + else + turfs_to_uncontain_by_zlevel[zlevel_to_clean] = list() + + +/// Ensures that the contained_turfs list properly represents the turfs actually inside us +/area/proc/cannonize_contained_turfs() + for (var/area_zlevel in 1 to length(turfs_to_uncontain_by_zlevel)) + cannonize_contained_turfs_by_zlevel(area_zlevel, _autoclean = FALSE) + + turfs_to_uncontain_by_zlevel = list() + /// Returns TRUE if we have contained turfs, FALSE otherwise /area/proc/has_contained_turfs() - return length(contained_turfs) - length(turfs_to_uncontain) > 0 + for (var/area_zlevel in 1 to length(turfs_by_zlevel)) + if (length(turfs_to_uncontain_by_zlevel) >= area_zlevel) + if (length(turfs_by_zlevel[area_zlevel]) - length(turfs_to_uncontain_by_zlevel[area_zlevel]) > 0) + return TRUE + else + if (length(turfs_by_zlevel[area_zlevel])) + return TRUE + return FALSE /** * Register this area as belonging to a z level @@ -286,8 +357,8 @@ GLOBAL_LIST_EMPTY(teleportlocs) air_vents = null air_scrubbers = null //turf cleanup - contained_turfs = null - turfs_to_uncontain = null + turfs_by_zlevel = null + turfs_to_uncontain_by_zlevel = null //parent cleanup return ..() @@ -521,8 +592,9 @@ GLOBAL_LIST_EMPTY(teleportlocs) if(outdoors) return FALSE areasize = 0 - for(var/turf/open/T in get_contained_turfs()) - areasize++ + for (var/list/zlevel_turfs as anything in get_zlevel_turf_lists()) + for(var/turf/open/thisvarisunused in zlevel_turfs) + areasize++ /** * Causes a runtime error diff --git a/code/game/atom/_atom.dm b/code/game/atom/_atom.dm index 66ed2048665..5bd8346f57f 100644 --- a/code/game/atom/_atom.dm +++ b/code/game/atom/_atom.dm @@ -296,7 +296,7 @@ if(mobile_docking_port.launch_status != check_for_launch_status) continue for(var/area/shuttle/shuttle_area as anything in mobile_docking_port.shuttle_areas) - if(current_turf in shuttle_area.get_contained_turfs()) + if(shuttle_area == current_turf.loc) return TRUE return FALSE diff --git a/code/game/objects/items/blueprints.dm b/code/game/objects/items/blueprints.dm index 4ccbf8319b0..82fc3437f20 100644 --- a/code/game/objects/items/blueprints.dm +++ b/code/game/objects/items/blueprints.dm @@ -238,7 +238,7 @@ return //stuff tied to the area to rename - var/list/to_rename = list( + var/static/list/to_rename = typecacheof(list( /obj/machinery/airalarm, /obj/machinery/atmospherics/components/unary/vent_scrubber, /obj/machinery/atmospherics/components/unary/vent_pump, @@ -246,11 +246,9 @@ /obj/machinery/firealarm, /obj/machinery/light_switch, /obj/machinery/power/apc, - ) - - for(var/turf/area_turf as anything in area.get_contained_turfs()) - for(var/obj/machine in area_turf) - if(!is_type_in_list(machine, to_rename)) - continue - machine.name = replacetext(machine.name, oldtitle, title) + )) + for (var/list/zlevel_turfs as anything in area.get_zlevel_turf_lists()) + for (var/turf/area_turf as anything in zlevel_turfs) + for(var/obj/machine as anything in typecache_filter_list(area_turf.contents, to_rename)) + machine.name = replacetext(machine.name, oldtitle, title) //TODO: much much more. Unnamed airlocks, cameras, etc. diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 8f29bb2e2c2..d62d523321b 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -228,9 +228,11 @@ GLOBAL_LIST_EMPTY(station_turfs) return //move the turf - old_area.turfs_to_uncontain += src + LISTASSERTLEN(old_area.turfs_to_uncontain_by_zlevel, z, list()) + LISTASSERTLEN(new_area.turfs_by_zlevel, z, list()) + old_area.turfs_to_uncontain_by_zlevel[z] += src + new_area.turfs_by_zlevel[z] += src new_area.contents += src - new_area.contained_turfs += src //changes to make after turf has moved on_change_area(old_area, new_area) diff --git a/code/game/world.dm b/code/game/world.dm index 99af6a6dbf0..ba8c653088d 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -389,7 +389,7 @@ GLOBAL_VAR(restart_counter) else if(SSticker.current_state == GAME_STATE_SETTING_UP) new_status += "
Starting: Now" else if(SSticker.IsRoundInProgress()) - new_status += "
Time: [time2text(((world.time - SSticker.round_start_time)/10), "hh:mm")]" + new_status += "
Time: [time2text(STATION_TIME_PASSED(), "hh:mm")]" if(SSshuttle?.emergency && SSshuttle?.emergency?.mode != (SHUTTLE_IDLE || SHUTTLE_ENDGAME)) new_status += " | Shuttle: [SSshuttle.emergency.getModeStr()] [SSshuttle.emergency.getTimerStr()]" else if(SSticker.current_state == GAME_STATE_FINISHED) @@ -424,10 +424,13 @@ GLOBAL_VAR(restart_counter) if(!map_load_z_cutoff) return var/area/global_area = GLOB.areas_by_type[world.area] // We're guaranteed to be touching the global area, so we'll just do this - var/list/to_add = block( - locate(old_max + 1, 1, 1), - locate(maxx, maxy, map_load_z_cutoff)) - global_area.contained_turfs += to_add + LISTASSERTLEN(global_area.turfs_by_zlevel, map_load_z_cutoff, list()) + for (var/zlevel in 1 to map_load_z_cutoff) + var/list/to_add = block( + locate(old_max + 1, 1, zlevel), + locate(maxx, maxy, zlevel)) + + global_area.turfs_by_zlevel[zlevel] += to_add /world/proc/increase_max_y(new_maxy, map_load_z_cutoff = maxz) if(new_maxy <= maxy) @@ -437,10 +440,12 @@ GLOBAL_VAR(restart_counter) if(!map_load_z_cutoff) return var/area/global_area = GLOB.areas_by_type[world.area] // We're guarenteed to be touching the global area, so we'll just do this - var/list/to_add = block( - locate(1, old_maxy + 1, 1), - locate(maxx, maxy, map_load_z_cutoff)) - global_area.contained_turfs += to_add + LISTASSERTLEN(global_area.turfs_by_zlevel, map_load_z_cutoff, list()) + for (var/zlevel in 1 to map_load_z_cutoff) + var/list/to_add = block( + locate(1, old_maxy + 1, 1), + locate(maxx, maxy, map_load_z_cutoff)) + global_area.turfs_by_zlevel[zlevel] += to_add /world/proc/incrementMaxZ() maxz++ diff --git a/code/modules/admin/verbs/adminjump.dm b/code/modules/admin/verbs/adminjump.dm index 1bdde584691..dfcc5f60dd0 100644 --- a/code/modules/admin/verbs/adminjump.dm +++ b/code/modules/admin/verbs/adminjump.dm @@ -10,10 +10,10 @@ return var/list/turfs = list() - for(var/turf/T in A.get_contained_turfs()) - if(T.density) - continue - turfs.Add(T) + for (var/list/zlevel_turfs as anything in A.get_zlevel_turf_lists()) + for (var/turf/area_turf as anything in zlevel_turfs) + if(!area_turf.density) + turfs.Add(area_turf) if(length(turfs)) var/turf/T = pick(turfs) diff --git a/code/modules/antagonists/nukeop/nukeop.dm b/code/modules/antagonists/nukeop/nukeop.dm index 68fe9b24778..f2a43718067 100644 --- a/code/modules/antagonists/nukeop/nukeop.dm +++ b/code/modules/antagonists/nukeop/nukeop.dm @@ -596,7 +596,7 @@ break var/list/turf/options = list() - for(var/turf/open/open_turf in spawn_in?.get_contained_turfs()) + for(var/turf/open/open_turf in spawn_in?.get_turfs_from_all_zlevels()) if(open_turf.is_blocked_turf()) continue options += open_turf diff --git a/code/modules/antagonists/traitor/objectives/kidnapping.dm b/code/modules/antagonists/traitor/objectives/kidnapping.dm index 3a614b348b0..5132815a864 100644 --- a/code/modules/antagonists/traitor/objectives/kidnapping.dm +++ b/code/modules/antagonists/traitor/objectives/kidnapping.dm @@ -275,7 +275,8 @@ return var/list/possible_turfs = list() - for(var/turf/open/open_turf in dropoff_area.get_contained_turfs()) + + for(var/turf/open/open_turf in dropoff_area.get_turfs_from_all_zlevels()) if(open_turf.is_blocked_turf() || isspaceturf(open_turf)) continue possible_turfs += open_turf diff --git a/code/modules/bitrunning/objects/landmarks.dm b/code/modules/bitrunning/objects/landmarks.dm index 0eb26b9c588..3a90939dae1 100644 --- a/code/modules/bitrunning/objects/landmarks.dm +++ b/code/modules/bitrunning/objects/landmarks.dm @@ -39,14 +39,15 @@ var/obj/structure/closet/crate/secure/bitrunning/encrypted/encrypted_crate var/area/my_area = get_area(src) - for(var/turf/area_turf as anything in my_area.get_contained_turfs()) - for(var/obj/structure/closet/crate/crate_to_check in area_turf) - if(istype(crate_to_check, /obj/structure/closet/crate/secure/bitrunning/encrypted)) - encrypted_crate = crate_to_check - crate_to_check.desc += span_hypnophrase(" This feels like the crate we're looking for!") - else - crate_list += crate_to_check - crate_to_check.name = "Unidentified Crate" + for (var/list/zlevel_turfs as anything in my_area.get_zlevel_turf_lists()) + for (var/turf/area_turf as anything in zlevel_turfs) + for(var/obj/structure/closet/crate/crate_to_check in area_turf) + if(istype(crate_to_check, /obj/structure/closet/crate/secure/bitrunning/encrypted)) + encrypted_crate = crate_to_check + crate_to_check.desc += span_hypnophrase(" This feels like the crate we're looking for!") + else + crate_list += crate_to_check + crate_to_check.name = "Unidentified Crate" if(!encrypted_crate) stack_trace("Bitrunning Goal Crate Randomizer failed to find an encrypted crate to swap positions for.") diff --git a/code/modules/cargo/expressconsole.dm b/code/modules/cargo/expressconsole.dm index 6babda045e0..79ae0b0fbf8 100644 --- a/code/modules/cargo/expressconsole.dm +++ b/code/modules/cargo/expressconsole.dm @@ -185,7 +185,7 @@ if (!landingzone) WARNING("[src] couldnt find a Quartermaster/Storage (aka cargobay) area on the station, and as such it has set the supplypod landingzone to the area it resides in.") landingzone = get_area(src) - for(var/turf/open/floor/T in landingzone.get_contained_turfs())//uses default landing zone + for(var/turf/open/floor/T in landingzone.get_turfs_from_all_zlevels())//uses default landing zone if(T.is_blocked_turf()) continue LAZYADD(empty_turfs, T) @@ -204,7 +204,7 @@ else if(SO.pack.get_cost() * (0.72*MAX_EMAG_ROCKETS) <= points_to_check) // bulk discount :^) landingzone = GLOB.areas_by_type[pick(GLOB.the_station_areas)] //override default landing zone - for(var/turf/open/floor/T in landingzone.get_contained_turfs()) + for(var/turf/open/floor/T in landingzone.get_turfs_from_all_zlevels()) if(T.is_blocked_turf()) continue LAZYADD(empty_turfs, T) diff --git a/code/modules/clothing/glasses/engine_goggles.dm b/code/modules/clothing/glasses/engine_goggles.dm index d91a5c3bb4a..c9fbb159126 100644 --- a/code/modules/clothing/glasses/engine_goggles.dm +++ b/code/modules/clothing/glasses/engine_goggles.dm @@ -97,15 +97,16 @@ return var/list/shuttle_areas = port.shuttle_areas for(var/area/region as anything in shuttle_areas) - for(var/turf/place as anything in region.get_contained_turfs()) - if(get_dist(user, place) > 7) - continue - var/image/pic - if(isshuttleturf(place)) - pic = new('icons/turf/overlays.dmi', place, "greenOverlay", AREA_LAYER) - else - pic = new('icons/turf/overlays.dmi', place, "redOverlay", AREA_LAYER) - flick_overlay_global(pic, list(user.client), 8) + for (var/list/zlevel_turfs as anything in region.get_zlevel_turf_lists()) + for (var/turf/place as anything in zlevel_turfs) + if(get_dist(user, place) > 7) + continue + var/image/pic + if(isshuttleturf(place)) + pic = new('icons/turf/overlays.dmi', place, "greenOverlay", AREA_LAYER) + else + pic = new('icons/turf/overlays.dmi', place, "redOverlay", AREA_LAYER) + flick_overlay_global(pic, list(user.client), 8) /obj/item/clothing/glasses/meson/engine/proc/show_connections() var/mob/living/carbon/human/user = loc diff --git a/code/modules/events/aurora_caelus.dm b/code/modules/events/aurora_caelus.dm index 8efe01169ce..34681825502 100644 --- a/code/modules/events/aurora_caelus.dm +++ b/code/modules/events/aurora_caelus.dm @@ -52,7 +52,7 @@ set_starlight(aurora_color) for(var/area/station/service/kitchen/affected_area in GLOB.areas) - for(var/turf/open/kitchen_floor in affected_area.get_contained_turfs()) + for(var/turf/open/kitchen_floor in affected_area.get_turfs_from_all_zlevels()) kitchen_floor.set_light(l_color = aurora_color) /datum/round_event/aurora_caelus/end() @@ -108,9 +108,9 @@ var/walked_range = LERP(start_range, end_range, i/5) var/walked_power = LERP(start_power, end_power, i/5) for(var/area/station/service/kitchen/affected_area in GLOB.areas) - for(var/turf/open/kitchen_floor in affected_area.get_contained_turfs()) + for(var/turf/open/kitchen_floor in affected_area.get_turfs_from_all_zlevels()) kitchen_floor.set_light(walked_range, walked_power, walked_color) sleep(8 SECONDS) for(var/area/station/service/kitchen/affected_area in GLOB.areas) - for(var/turf/open/kitchen_floor in affected_area.get_contained_turfs()) + for(var/turf/open/kitchen_floor in affected_area.get_turfs_from_all_zlevels()) kitchen_floor.set_light(end_range, end_power, end_color) diff --git a/code/modules/events/shuttle_loan/shuttle_loan_event.dm b/code/modules/events/shuttle_loan/shuttle_loan_event.dm index e0b5cccb1ee..ac5faa6971f 100644 --- a/code/modules/events/shuttle_loan/shuttle_loan_event.dm +++ b/code/modules/events/shuttle_loan/shuttle_loan_event.dm @@ -80,7 +80,7 @@ var/list/blocked_shutte_turfs = list() var/list/area/shuttle/shuttle_areas = SSshuttle.supply.shuttle_areas for(var/area/shuttle/shuttle_area as anything in shuttle_areas) - for(var/turf/open/floor/shuttle_turf in shuttle_area.get_contained_turfs()) + for(var/turf/open/floor/shuttle_turf in shuttle_area.get_turfs_from_all_zlevels()) if(shuttle_turf.is_blocked_turf()) blocked_shutte_turfs += shuttle_turf continue diff --git a/code/modules/events/space_vines/vine_event.dm b/code/modules/events/space_vines/vine_event.dm index 46cf91a33e6..03350abdb09 100644 --- a/code/modules/events/space_vines/vine_event.dm +++ b/code/modules/events/space_vines/vine_event.dm @@ -38,7 +38,7 @@ var/obj/structure/spacevine/vine = new() for(var/area/station/hallway/area in GLOB.areas) - for(var/turf/open/floor in area.get_contained_turfs()) + for(var/turf/open/floor in area.get_turfs_from_all_zlevels()) if(floor.Enter(vine)) turfs += floor diff --git a/code/modules/holodeck/items.dm b/code/modules/holodeck/items.dm index 10229929c84..eb0261739ad 100644 --- a/code/modules/holodeck/items.dm +++ b/code/modules/holodeck/items.dm @@ -119,11 +119,12 @@ var/numbuttons = 0 var/numready = 0 - for(var/turf/area_turf as anything in currentarea.get_contained_turfs()) - for(var/obj/machinery/readybutton/button in area_turf) - numbuttons++ - if(button.ready) - numready++ + for (var/list/zlevel_turfs as anything in currentarea.get_zlevel_turf_lists()) + for (var/turf/area_turf as anything in zlevel_turfs) + for(var/obj/machinery/readybutton/button in area_turf) + numbuttons++ + if(button.ready) + numready++ if(numbuttons == numready) begin_event() @@ -136,13 +137,14 @@ eventstarted = TRUE - for(var/turf/area_turf as anything in currentarea.get_contained_turfs()) - for(var/obj/structure/window/barrier in area_turf) - if((barrier.obj_flags & NO_DECONSTRUCTION) || (barrier.flags_1 & HOLOGRAM_1))// Just in case: only holo-windows - qdel(barrier) + for (var/list/zlevel_turfs as anything in currentarea.get_zlevel_turf_lists()) + for(var/turf/area_turf as anything in zlevel_turfs) + for(var/obj/structure/window/barrier in area_turf) + if((barrier.obj_flags & NO_DECONSTRUCTION) || (barrier.flags_1 & HOLOGRAM_1))// Just in case: only holo-windows + qdel(barrier) - for(var/mob/contestant in area_turf) - to_chat(contestant, span_userdanger("FIGHT!")) + for(var/mob/contestant in area_turf) + to_chat(contestant, span_userdanger("FIGHT!")) /obj/machinery/conveyor/holodeck diff --git a/code/modules/lighting/lighting_area.dm b/code/modules/lighting/lighting_area.dm index c6f427f592f..84170b6964f 100644 --- a/code/modules/lighting/lighting_area.dm +++ b/code/modules/lighting/lighting_area.dm @@ -51,9 +51,10 @@ UnregisterSignal(SSdcs, COMSIG_STARLIGHT_COLOR_CHANGED) var/list/z_offsets = SSmapping.z_level_to_plane_offset if(length(lighting_effects) > 1) - for(var/turf/T as anything in get_contained_turfs()) - if(z_offsets[T.z]) - T.cut_overlay(lighting_effects[z_offsets[T.z] + 1]) + for(var/area_zlevel as anything in 1 to get_highest_zlevel()) + if(z_offsets[area_zlevel]) + for(var/turf/T as anything in get_turfs_by_zlevel(area_zlevel)) + T.cut_overlay(lighting_effects[z_offsets[T.z] + 1]) cut_overlay(lighting_effects[1]) lighting_effects = null area_has_base_lighting = FALSE @@ -91,17 +92,18 @@ add_overlay(lighting_effects[1]) var/list/z_offsets = SSmapping.z_level_to_plane_offset - if(length(lighting_effects) > 1) - // This inside loop is EXTREMELY hot because it's run by space tiles. Don't want no part in that - for(var/turf/T as anything in get_contained_turfs()) - T.luminosity = 1 - // We will only add overlays to turfs not on the first z layer, because that's a significantly lesser portion - // And we need to do them separate, or lighting will go fuckey - if(z_offsets[T.z]) - T.add_overlay(lighting_effects[z_offsets[T.z] + 1]) - else - for(var/turf/T as anything in get_contained_turfs()) - T.luminosity = 1 + for (var/area_zlevel in 1 to get_highest_zlevel()) + // We will only add overlays to turfs not on the first z layer, because that's a significantly lesser portion + // And we need to do them separate, or lighting will go fuckey + // This inside loop is EXTREMELY hot because it's run by space tiles, so we do the if check once on the outside + if(length(lighting_effects) > 1 && z_offsets[area_zlevel]) + var/lighting_effect_to_add = lighting_effects[z_offsets[area_zlevel] + 1] + for(var/turf/area_turf as anything in get_turfs_by_zlevel(area_zlevel)) + area_turf.luminosity = 1 + area_turf.add_overlay(lighting_effect_to_add) + else + for(var/turf/area_turf as anything in get_turfs_by_zlevel(area_zlevel)) + area_turf.luminosity = 1 area_has_base_lighting = TRUE diff --git a/code/modules/lighting/lighting_setup.dm b/code/modules/lighting/lighting_setup.dm index d6bf19711ef..c148530d1cd 100644 --- a/code/modules/lighting/lighting_setup.dm +++ b/code/modules/lighting/lighting_setup.dm @@ -1,12 +1,12 @@ /proc/create_all_lighting_objects() - for(var/area/A as anything in GLOB.areas) - if(!A.static_lighting) + for(var/area/area as anything in GLOB.areas) + if(!area.static_lighting) continue - - for(var/turf/T as anything in A.get_contained_turfs()) - if(T.space_lit) - continue - new /datum/lighting_object(T) + for (var/list/zlevel_turfs as anything in area.get_zlevel_turf_lists()) + for(var/turf/area_turf as anything in zlevel_turfs) + if(area_turf.space_lit) + continue + new /datum/lighting_object(area_turf) CHECK_TICK CHECK_TICK diff --git a/code/modules/mapping/mapping_helpers.dm b/code/modules/mapping/mapping_helpers.dm index 9c5ac879aee..7676801a0a9 100644 --- a/code/modules/mapping/mapping_helpers.dm +++ b/code/modules/mapping/mapping_helpers.dm @@ -867,11 +867,12 @@ INITIALIZE_IMMEDIATE(/obj/effect/mapping_helpers/no_lava) /obj/effect/mapping_helpers/dead_body_placer/LateInitialize() var/area/morgue_area = get_area(src) var/list/obj/structure/bodycontainer/morgue/trays = list() - for(var/turf/area_turf as anything in morgue_area.get_contained_turfs()) - var/obj/structure/bodycontainer/morgue/morgue_tray = locate() in area_turf - if(isnull(morgue_tray) || !morgue_tray.beeper || morgue_tray.connected.loc != morgue_tray) - continue - trays += morgue_tray + for (var/list/zlevel_turfs as anything in morgue_area.get_zlevel_turf_lists()) + for(var/turf/area_turf as anything in zlevel_turfs) + var/obj/structure/bodycontainer/morgue/morgue_tray = locate() in area_turf + if(isnull(morgue_tray) || !morgue_tray.beeper || morgue_tray.connected.loc != morgue_tray) + continue + trays += morgue_tray var/numtrays = length(trays) if(numtrays == 0) @@ -959,14 +960,15 @@ INITIALIZE_IMMEDIATE(/obj/effect/mapping_helpers/no_lava) var/list/table_turfs = list() var/list/open_turfs = list() var/turf/dogbed_turf - for(var/turf/area_turf as anything in celebration_area.get_contained_turfs()) - if(locate(/obj/structure/table/reinforced) in area_turf) - table_turfs += area_turf - if(locate(/obj/structure/bed/dogbed/ian) in area_turf) - dogbed_turf = area_turf - if(isopenturf(area_turf)) - new /obj/effect/decal/cleanable/confetti(area_turf) - open_turfs += area_turf + for (var/list/zlevel_turfs as anything in celebration_area.get_zlevel_turf_lists()) + for(var/turf/area_turf as anything in zlevel_turfs) + if(locate(/obj/structure/table/reinforced) in area_turf) + table_turfs += area_turf + if(locate(/obj/structure/bed/dogbed/ian) in area_turf) + dogbed_turf = area_turf + if(isopenturf(area_turf)) + new /obj/effect/decal/cleanable/confetti(area_turf) + open_turfs += area_turf if(isnull(dogbed_turf) && map_warning) log_mapping("[src] in [celebration_area] could not find Ian's dogbed.") @@ -1031,11 +1033,12 @@ INITIALIZE_IMMEDIATE(/obj/effect/mapping_helpers/no_lava) var/area/celebration_area = get_area(src) var/list/table_turfs = list() var/turf/dogbed_turf - for(var/turf/area_turf as anything in celebration_area.get_contained_turfs()) - if(locate(/obj/structure/table/reinforced) in area_turf) - table_turfs += area_turf - if(locate(/obj/structure/bed/dogbed/ian) in area_turf) - dogbed_turf = area_turf + for (var/list/zlevel_turfs as anything in celebration_area.get_zlevel_turf_lists()) + for(var/turf/area_turf as anything in zlevel_turfs) + if(locate(/obj/structure/table/reinforced) in area_turf) + table_turfs += area_turf + if(locate(/obj/structure/bed/dogbed/ian) in area_turf) + dogbed_turf = area_turf if(isnull(dogbed_turf)) log_mapping("[src] in [celebration_area] could not find Ian's dogbed.") diff --git a/code/modules/mapping/reader.dm b/code/modules/mapping/reader.dm index ab6743ff17a..b8db314117f 100644 --- a/code/modules/mapping/reader.dm +++ b/code/modules/mapping/reader.dm @@ -930,8 +930,10 @@ GLOBAL_LIST_EMPTY(map_model_default) if(!new_z) old_area = crds.loc - old_area.turfs_to_uncontain += crds - area_instance.contained_turfs.Add(crds) + LISTASSERTLEN(old_area.turfs_to_uncontain_by_zlevel, crds.z, list()) + LISTASSERTLEN(area_instance.turfs_by_zlevel, crds.z, list()) + old_area.turfs_to_uncontain_by_zlevel[crds.z] += crds + area_instance.turfs_by_zlevel[crds.z] += crds area_instance.contents.Add(crds) if(GLOB.use_preloader) diff --git a/code/modules/mapping/space_management/space_reservation.dm b/code/modules/mapping/space_management/space_reservation.dm index 2809ae65e6c..04ba59ab5a4 100644 --- a/code/modules/mapping/space_management/space_reservation.dm +++ b/code/modules/mapping/space_management/space_reservation.dm @@ -81,9 +81,13 @@ for(var/turf/cordon_turf as anything in cordon_turfs) var/area/misc/cordon/cordon_area = GLOB.areas_by_type[/area/misc/cordon] || new var/area/old_area = cordon_turf.loc - old_area.turfs_to_uncontain += cordon_turf - cordon_area.contained_turfs += cordon_turf + + LISTASSERTLEN(old_area.turfs_to_uncontain_by_zlevel, cordon_turf.z, list()) + LISTASSERTLEN(cordon_area.turfs_by_zlevel, cordon_turf.z, list()) + old_area.turfs_to_uncontain_by_zlevel[cordon_turf.z] += cordon_turf + cordon_area.turfs_by_zlevel[cordon_turf.z] += cordon_turf cordon_area.contents += cordon_turf + // Its no longer unused, but its also not "used" cordon_turf.turf_flags &= ~UNUSED_RESERVATION_TURF cordon_turf.ChangeTurf(/turf/cordon, /turf/cordon) diff --git a/code/modules/mob/living/simple_animal/bot/mulebot.dm b/code/modules/mob/living/simple_animal/bot/mulebot.dm index 88210a714c8..7e3b0ab0c2e 100644 --- a/code/modules/mob/living/simple_animal/bot/mulebot.dm +++ b/code/modules/mob/living/simple_animal/bot/mulebot.dm @@ -815,39 +815,37 @@ load(AM) -/mob/living/simple_animal/bot/mulebot/paranormal/load(atom/movable/AM) - if(load || AM.anchored) +/mob/living/simple_animal/bot/mulebot/paranormal/load(atom/movable/movable_atom) + if(load || movable_atom.anchored) return - if(!isturf(AM.loc)) //To prevent the loading from stuff from someone's inventory or screen icons. + if(!isturf(movable_atom.loc)) //To prevent the loading from stuff from someone's inventory or screen icons. return - if(isobserver(AM)) + if(isobserver(movable_atom)) visible_message(span_warning("A ghostly figure appears on [src]!")) - RegisterSignal(AM, COMSIG_MOVABLE_MOVED, PROC_REF(ghostmoved)) - AM.forceMove(src) + movable_atom.forceMove(src) + RegisterSignal(movable_atom, COMSIG_MOVABLE_MOVED, PROC_REF(ghostmoved)) else if(!wires.is_cut(WIRE_LOADCHECK)) buzz(SIGH) return // if not hacked, only allow ghosts to be loaded - else if(isobj(AM)) - var/obj/O = AM - if(O.has_buckled_mobs() || (locate(/mob) in AM)) //can't load non crates objects with mobs buckled to it or inside it. + else if(isobj(movable_atom)) + if(movable_atom.has_buckled_mobs() || (locate(/mob) in movable_atom)) //can't load non crates objects with mobs buckled to it or inside it. buzz(SIGH) return - if(istype(O, /obj/structure/closet/crate)) - var/obj/structure/closet/crate/crate = O + if(istype(movable_atom, /obj/structure/closet/crate)) + var/obj/structure/closet/crate/crate = movable_atom crate.close() //make sure it's closed - O.forceMove(src) + movable_atom.forceMove(src) - else if(isliving(AM)) - if(!load_mob(AM)) //buckling is handled in forceMove() - return + else if(isliving(movable_atom) && !load_mob(movable_atom)) + return - load = AM + load = movable_atom mode = BOT_IDLE update_appearance() diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm index 6be52bf1c85..e394ea18db9 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm @@ -366,7 +366,7 @@ var/area/current_area = get_area(src) if (current_area in converted_areas) return FALSE - terrain_theme.apply_theme_to_list_of_turfs(current_area.get_contained_turfs()) + terrain_theme.apply_theme_to_list_of_turfs(current_area.get_turfs_from_all_zlevels()) converted_areas += current_area return TRUE diff --git a/code/modules/power/apc/apc_main.dm b/code/modules/power/apc/apc_main.dm index cbc1db293e7..b11b6c8b413 100644 --- a/code/modules/power/apc/apc_main.dm +++ b/code/modules/power/apc/apc_main.dm @@ -463,12 +463,13 @@ update() if("emergency_lighting") emergency_lights = !emergency_lights - for(var/turf/area_turf as anything in area.get_contained_turfs()) - for(var/obj/machinery/light/area_light in area_turf) - if(!initial(area_light.no_low_power)) //If there was an override set on creation, keep that override - area_light.no_low_power = emergency_lights - INVOKE_ASYNC(area_light, TYPE_PROC_REF(/obj/machinery/light/, update), FALSE) - CHECK_TICK + for (var/list/zlevel_turfs as anything in area.get_zlevel_turf_lists()) + for(var/turf/area_turf as anything in zlevel_turfs) + for(var/obj/machinery/light/area_light in area_turf) + if(!initial(area_light.no_low_power)) //If there was an override set on creation, keep that override + area_light.no_low_power = emergency_lights + INVOKE_ASYNC(area_light, TYPE_PROC_REF(/obj/machinery/light/, update), FALSE) + CHECK_TICK return TRUE /obj/machinery/power/apc/ui_close(mob/user) @@ -678,11 +679,12 @@ INVOKE_ASYNC(src, PROC_REF(break_lights)) /obj/machinery/power/apc/proc/break_lights() - for(var/turf/area_turf as anything in area.get_contained_turfs()) - for(var/obj/machinery/light/breaked_light in area_turf) - breaked_light.on = TRUE - breaked_light.break_light_tube() - stoplag() + for (var/list/zlevel_turfs as anything in area.get_zlevel_turf_lists()) + for(var/turf/area_turf as anything in zlevel_turfs) + for(var/obj/machinery/light/breaked_light in area_turf) + breaked_light.on = TRUE + breaked_light.break_light_tube() + stoplag() /obj/machinery/power/apc/should_atmos_process(datum/gas_mixture/air, exposed_temperature) return (exposed_temperature > 2000) diff --git a/code/modules/power/apc/apc_power_proc.dm b/code/modules/power/apc/apc_power_proc.dm index 6118791c15c..52a671f00f5 100644 --- a/code/modules/power/apc/apc_power_proc.dm +++ b/code/modules/power/apc/apc_power_proc.dm @@ -138,9 +138,10 @@ if(nightshift_lights == on) return //no change nightshift_lights = on - for(var/turf/area_turf as anything in area.get_contained_turfs()) - for(var/obj/machinery/light/night_light in area_turf) - if(night_light.nightshift_allowed) - night_light.nightshift_enabled = nightshift_lights - night_light.update(FALSE) - CHECK_TICK + for (var/list/zlevel_turfs as anything in area.get_zlevel_turf_lists()) + for(var/turf/area_turf as anything in zlevel_turfs) + for(var/obj/machinery/light/night_light in area_turf) + if(night_light.nightshift_allowed) + night_light.nightshift_enabled = nightshift_lights + night_light.update(FALSE) + CHECK_TICK diff --git a/code/modules/research/xenobiology/crossbreeding/chilling.dm b/code/modules/research/xenobiology/crossbreeding/chilling.dm index 1eec00033e5..8890db9a890 100644 --- a/code/modules/research/xenobiology/crossbreeding/chilling.dm +++ b/code/modules/research/xenobiology/crossbreeding/chilling.dm @@ -58,9 +58,10 @@ Chilling extracts: to_chat(user, span_warning("[src] can't affect such a large area.")) return user.visible_message(span_notice("[src] shatters, and a healing aura fills the room briefly.")) - for(var/turf/area_turf as anything in user_area.get_contained_turfs()) - for(var/mob/living/carbon/nearby in area_turf) - nearby.reagents?.add_reagent(/datum/reagent/medicine/regen_jelly,10) + for (var/list/zlevel_turfs as anything in user_area.get_zlevel_turf_lists()) + for(var/turf/area_turf as anything in zlevel_turfs) + for(var/mob/living/carbon/nearby in area_turf) + nearby.reagents?.add_reagent(/datum/reagent/medicine/regen_jelly,10) ..() /obj/item/slimecross/chilling/blue @@ -108,7 +109,7 @@ Chilling extracts: to_chat(user, span_warning("[src] can't affect such a large area.")) return var/filtered = FALSE - for(var/turf/open/T in A.get_contained_turfs()) + for(var/turf/open/T in A.get_turfs_from_all_zlevels()) var/datum/gas_mixture/G = T.air if(istype(G)) G.assert_gas(/datum/gas/plasma) @@ -336,7 +337,8 @@ Chilling extracts: to_chat(user, span_warning("[src] can't affect such a large area.")) return user.visible_message(span_warning("[src] reflects an array of dazzling colors and light, energy rushing to nearby doors!")) - for(var/turf/area_turf as anything in area.get_contained_turfs()) - for(var/obj/machinery/door/airlock/door in area_turf) - new /obj/effect/forcefield/slimewall/rainbow(door.loc) + for (var/list/zlevel_turfs as anything in area.get_zlevel_turf_lists()) + for(var/turf/area_turf as anything in zlevel_turfs) + for(var/obj/machinery/door/airlock/door in area_turf) + new /obj/effect/forcefield/slimewall/rainbow(door.loc) return ..() diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm index efc6f3aa8b0..49f7bfa61f3 100644 --- a/code/modules/research/xenobiology/xenobiology.dm +++ b/code/modules/research/xenobiology/xenobiology.dm @@ -1065,9 +1065,10 @@ /obj/item/areaeditor/blueprints/slime/edit_area() ..() - var/area/A = get_area(src) - for(var/turf/T as anything in A.get_contained_turfs()) - T.remove_atom_colour(WASHABLE_COLOUR_PRIORITY) - T.add_atom_colour("#2956B2", FIXED_COLOUR_PRIORITY) - A.area_flags |= XENOBIOLOGY_COMPATIBLE + var/area/area = get_area(src) + for (var/list/zlevel_turfs as anything in area.get_zlevel_turf_lists()) + for(var/turf/area_turf as anything in zlevel_turfs) + area_turf.remove_atom_colour(WASHABLE_COLOUR_PRIORITY) + area_turf.add_atom_colour("#2956B2", FIXED_COLOUR_PRIORITY) + area.area_flags |= XENOBIOLOGY_COMPATIBLE qdel(src) diff --git a/code/modules/security_levels/keycard_authentication.dm b/code/modules/security_levels/keycard_authentication.dm index a3cda3fda0f..5e193e4dbf6 100644 --- a/code/modules/security_levels/keycard_authentication.dm +++ b/code/modules/security_levels/keycard_authentication.dm @@ -180,21 +180,25 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/keycard_auth, 26) GLOBAL_VAR_INIT(emergency_access, FALSE) /proc/make_maint_all_access() - for(var/area/station/maintenance/A in GLOB.areas) - for(var/turf/in_area as anything in A.get_contained_turfs()) - for(var/obj/machinery/door/airlock/D in in_area) - D.emergency = TRUE - D.update_icon(ALL, 0) + for(var/area/station/maintenance/area in GLOB.areas) + for (var/list/zlevel_turfs as anything in area.get_zlevel_turf_lists()) + for(var/turf/area_turf as anything in zlevel_turfs) + for(var/obj/machinery/door/airlock/airlock in area_turf) + airlock.emergency = TRUE + airlock.update_icon(ALL, 0) + minor_announce("Access restrictions on maintenance and external airlocks have been lifted.", "Attention! Station-wide emergency declared!",1) GLOB.emergency_access = TRUE SSblackbox.record_feedback("nested tally", "keycard_auths", 1, list("emergency maintenance access", "enabled")) /proc/revoke_maint_all_access() - for(var/area/station/maintenance/A in GLOB.areas) - for(var/turf/in_area as anything in A.get_contained_turfs()) - for(var/obj/machinery/door/airlock/D in in_area) - D.emergency = FALSE - D.update_icon(ALL, 0) + for(var/area/station/maintenance/area in GLOB.areas) + for (var/list/zlevel_turfs as anything in area.get_zlevel_turf_lists()) + for(var/turf/area_turf as anything in zlevel_turfs) + for(var/obj/machinery/door/airlock/airlock in area_turf) + airlock.emergency = FALSE + airlock.update_icon(ALL, 0) + minor_announce("Access restrictions in maintenance areas have been restored.", "Attention! Station-wide emergency rescinded:") GLOB.emergency_access = FALSE SSblackbox.record_feedback("nested tally", "keycard_auths", 1, list("emergency maintenance access", "disabled")) diff --git a/code/modules/shuttle/arrivals.dm b/code/modules/shuttle/arrivals.dm index 81b456603b4..3b32bec5539 100644 --- a/code/modules/shuttle/arrivals.dm +++ b/code/modules/shuttle/arrivals.dm @@ -37,11 +37,12 @@ var/list/new_latejoin = list() for(var/area/shuttle/arrival/arrival_area in GLOB.areas) - for(var/turf/arrival_turf as anything in arrival_area.get_contained_turfs()) - for(var/obj/structure/chair/shuttle_chair in arrival_turf) - new_latejoin += shuttle_chair - if(isnull(console)) - console = locate() in arrival_turf + for (var/list/zlevel_turfs as anything in arrival_area.get_zlevel_turf_lists()) + for(var/turf/arrival_turf as anything in zlevel_turfs) + for(var/obj/structure/chair/shuttle_chair in arrival_turf) + new_latejoin += shuttle_chair + if(isnull(console)) + console = locate() in arrival_turf areas += arrival_area if(SSjob.latejoin_trackers.len) diff --git a/code/modules/shuttle/navigation_computer.dm b/code/modules/shuttle/navigation_computer.dm index e564247bee4..a5479e02016 100644 --- a/code/modules/shuttle/navigation_computer.dm +++ b/code/modules/shuttle/navigation_computer.dm @@ -96,17 +96,18 @@ the_eye.setDir(shuttle_port.dir) var/turf/origin = locate(shuttle_port.x + x_offset, shuttle_port.y + y_offset, shuttle_port.z) for(var/area/shuttle_area as anything in shuttle_port.shuttle_areas) - for(var/turf/shuttle_turf as anything in shuttle_area.get_contained_turfs()) - if(shuttle_turf.z != origin.z) - continue - var/image/I = image('icons/effects/alphacolors.dmi', origin, "red") - var/x_off = shuttle_turf.x - origin.x - var/y_off = shuttle_turf.y - origin.y - I.loc = locate(origin.x + x_off, origin.y + y_off, origin.z) //we have to set this after creating the image because it might be null, and images created in nullspace are immutable. - I.layer = ABOVE_NORMAL_TURF_LAYER - SET_PLANE(I, ABOVE_GAME_PLANE, shuttle_turf) - I.mouse_opacity = MOUSE_OPACITY_TRANSPARENT - the_eye.placement_images[I] = list(x_off, y_off) + for (var/list/zlevel_turfs as anything in shuttle_area.get_zlevel_turf_lists()) + for(var/turf/shuttle_turf as anything in zlevel_turfs) + if(shuttle_turf.z != origin.z) + continue + var/image/I = image('icons/effects/alphacolors.dmi', origin, "red") + var/x_off = shuttle_turf.x - origin.x + var/y_off = shuttle_turf.y - origin.y + I.loc = locate(origin.x + x_off, origin.y + y_off, origin.z) //we have to set this after creating the image because it might be null, and images created in nullspace are immutable. + I.layer = ABOVE_NORMAL_TURF_LAYER + SET_PLANE(I, ABOVE_GAME_PLANE, shuttle_turf) + I.mouse_opacity = MOUSE_OPACITY_TRANSPARENT + the_eye.placement_images[I] = list(x_off, y_off) /obj/machinery/computer/camera_advanced/shuttle_docker/give_eye_control(mob/user) ..() diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm index d9e20b07f1b..c46f68c2fb2 100644 --- a/code/modules/shuttle/shuttle.dm +++ b/code/modules/shuttle/shuttle.dm @@ -516,13 +516,14 @@ var/min_y = -1 var/max_x = WORLDMAXX_CUTOFF var/max_y = WORLDMAXY_CUTOFF - for(var/area/area as anything in shuttle_areas) - for(var/turf/turf as anything in area.get_contained_turfs()) - min_x = max(turf.x, min_x) - max_x = min(turf.x, max_x) - min_y = max(turf.y, min_y) - max_y = min(turf.y, max_y) - CHECK_TICK + for(var/area/shuttle_area as anything in shuttle_areas) + for (var/list/zlevel_turfs as anything in shuttle_area.get_zlevel_turf_lists()) + for(var/turf/turf as anything in zlevel_turfs) + min_x = max(turf.x, min_x) + max_x = min(turf.x, max_x) + min_y = max(turf.y, min_y) + max_y = min(turf.y, max_y) + CHECK_TICK if(min_x == -1 || max_x == WORLDMAXX_CUTOFF) CRASH("Failed to locate shuttle boundaries when iterating through shuttle areas, somehow.") diff --git a/code/modules/shuttle/supply.dm b/code/modules/shuttle/supply.dm index 515d3b38cfe..f07444c22f1 100644 --- a/code/modules/shuttle/supply.dm +++ b/code/modules/shuttle/supply.dm @@ -59,22 +59,23 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list( return ..() /obj/docking_port/mobile/supply/proc/check_blacklist(areaInstances) - for(var/place in areaInstances) - var/area/shuttle/shuttle_area = place - for(var/turf/shuttle_turf in shuttle_area.get_contained_turfs()) - for(var/atom/passenger in shuttle_turf.get_all_contents()) - if((is_type_in_typecache(passenger, GLOB.blacklisted_cargo_types) || HAS_TRAIT(passenger, TRAIT_BANNED_FROM_CARGO_SHUTTLE)) && !istype(passenger, /obj/docking_port)) - return FALSE + for(var/area/shuttle_area as anything in areaInstances) + for (var/list/zlevel_turfs as anything in shuttle_area.get_zlevel_turf_lists()) + for(var/turf/shuttle_turf as anything in zlevel_turfs) + for(var/atom/passenger in shuttle_turf.get_all_contents()) + if((is_type_in_typecache(passenger, GLOB.blacklisted_cargo_types) || HAS_TRAIT(passenger, TRAIT_BANNED_FROM_CARGO_SHUTTLE)) && !istype(passenger, /obj/docking_port)) + return FALSE return TRUE /// Returns anything on the cargo blacklist found within areas_to_check back to the turf of the home docking port via Centcom branded supply pod. /obj/docking_port/mobile/supply/proc/return_blacklisted_things_home(list/area/areas_to_check, obj/docking_port/stationary/home) var/list/stuff_to_send_home = list() for(var/area/shuttle_area as anything in areas_to_check) - for(var/turf/shuttle_turf in shuttle_area.get_contained_turfs()) - for(var/atom/passenger in shuttle_turf.get_all_contents()) - if((is_type_in_typecache(passenger, GLOB.blacklisted_cargo_types) || HAS_TRAIT(passenger, TRAIT_BANNED_FROM_CARGO_SHUTTLE)) && !istype(passenger, /obj/docking_port)) - stuff_to_send_home += passenger + for (var/list/zlevel_turfs as anything in shuttle_area.get_zlevel_turf_lists()) + for(var/turf/shuttle_turf as anything in zlevel_turfs) + for(var/atom/passenger in shuttle_turf.get_all_contents()) + if((is_type_in_typecache(passenger, GLOB.blacklisted_cargo_types) || HAS_TRAIT(passenger, TRAIT_BANNED_FROM_CARGO_SHUTTLE)) && !istype(passenger, /obj/docking_port)) + stuff_to_send_home += passenger if(!length(stuff_to_send_home)) return FALSE @@ -135,7 +136,7 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list( var/list/empty_turfs = list() for(var/area/shuttle/shuttle_area as anything in shuttle_areas) - for(var/turf/open/floor/shuttle_turf in shuttle_area.get_contained_turfs()) + for(var/turf/open/floor/shuttle_turf in shuttle_area.get_turfs_from_all_zlevels()) if(shuttle_turf.is_blocked_turf()) continue empty_turfs += shuttle_turf @@ -283,13 +284,14 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list( var/datum/export_report/report = new for(var/area/shuttle/shuttle_area as anything in shuttle_areas) - for(var/turf/shuttle_turf as anything in shuttle_area.get_contained_turfs()) - for(var/atom/movable/exporting_atom in shuttle_turf) - if(iscameramob(exporting_atom)) - continue - if(exporting_atom.anchored) - continue - export_item_and_contents(exporting_atom, apply_elastic = TRUE, dry_run = FALSE, external_report = report) + for (var/list/zlevel_turfs as anything in shuttle_area.get_zlevel_turf_lists()) + for(var/turf/shuttle_turf as anything in zlevel_turfs) + for(var/atom/movable/exporting_atom in shuttle_turf) + if(iscameramob(exporting_atom)) + continue + if(exporting_atom.anchored) + continue + export_item_and_contents(exporting_atom, apply_elastic = TRUE, dry_run = FALSE, external_report = report) if(report.exported_atoms) report.exported_atoms += "." //ugh @@ -318,7 +320,7 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list( //spawn crate var/list/empty_turfs = list() for(var/area/shuttle/shuttle_area as anything in shuttle_areas) - for(var/turf/open/floor/shuttle_floor in shuttle_area.get_contained_turfs()) + for(var/turf/open/floor/shuttle_floor in shuttle_area.get_turfs_from_all_zlevels()) if(shuttle_floor.is_blocked_turf()) continue empty_turfs += shuttle_floor diff --git a/code/modules/unit_tests/area_contents.dm b/code/modules/unit_tests/area_contents.dm index 8a48d644ee9..52394dd60ec 100644 --- a/code/modules/unit_tests/area_contents.dm +++ b/code/modules/unit_tests/area_contents.dm @@ -6,23 +6,28 @@ /datum/unit_test/area_contents/Run() // First, we check that there are no entries in more then one area // That or duplicate entries - for(var/area/space in GLOB.areas) - for(var/turf/position as anything in space.get_contained_turfs()) - if(!isturf(position)) - TEST_FAIL("Found a [position.type] in [space.type]'s turf listing") + for (var/area/area_to_test in GLOB.areas) + area_to_test.cannonize_contained_turfs() + for (var/i in 1 to area_to_test.turfs_by_zlevel.len) + if (!islist(area_to_test.turfs_by_zlevel[i])) + TEST_FAIL("zlevel index [i] in [area_to_test.type] is not a list.") - if(position.in_contents_of) - var/area/existing = position.in_contents_of - if(existing == space) - TEST_FAIL("Found a duplicate turf [position.type] inside [space.type]'s turf listing") - else - TEST_FAIL("Found a shared turf [position.type] between [space.type] and [existing.type]'s turf listings") + for (var/turf/turf_to_check as anything in area_to_test.turfs_by_zlevel[i]) + if (!isturf(turf_to_check)) + TEST_FAIL("Found a [turf_to_check.type] in [area_to_test.type]'s turf listing") - var/area/dream_spot = position.loc - if(dream_spot != space) - TEST_FAIL("Found a turf [position.type] which is IN [dream_spot.type], but is registered as being in [space.type]") + if (turf_to_check.in_contents_of) + var/area/existing = turf_to_check.in_contents_of + if (existing == turf_to_check) + TEST_FAIL("Found a duplicate turf [turf_to_check.type] inside [area_to_test.type]'s turf listing") + else + TEST_FAIL("Found a shared turf [turf_to_check.type] between [area_to_test.type] and [existing.type]'s turf listings") - position.in_contents_of = space + var/area/turfs_actual_area = turf_to_check.loc + if (turfs_actual_area != area_to_test) + TEST_FAIL("Found a turf [turf_to_check.type] which is IN [turfs_actual_area.type], but is registered as being in [area_to_test.type]") + + turf_to_check.in_contents_of = turf_to_check for(var/turf/position in ALL_TURFS()) if(!position.in_contents_of) diff --git a/code/modules/unit_tests/atmospherics_sanity.dm b/code/modules/unit_tests/atmospherics_sanity.dm index c4f024e9178..ff177ae4517 100644 --- a/code/modules/unit_tests/atmospherics_sanity.dm +++ b/code/modules/unit_tests/atmospherics_sanity.dm @@ -101,7 +101,7 @@ UNTIL(crawls == 0) for(var/area/missed as anything in remaining_areas) if(missed.has_contained_turfs()) - var/turf/first_turf = missed.get_contained_turfs()[1] + var/turf/first_turf = missed.get_zlevel_turf_lists()[1][1] TEST_FAIL("Disconnected Area '[missed]'([missed.type]) at ([first_turf.x], [first_turf.y], [first_turf.z])") else TEST_NOTICE(src, "Disconnected Area '[missed]'([missed.type]) with no turfs?") diff --git a/html/changelogs/AutoChangeLog-pr-80986.yml b/html/changelogs/AutoChangeLog-pr-80986.yml new file mode 100644 index 00000000000..0adaeb6b55f --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-80986.yml @@ -0,0 +1,4 @@ +author: "Ghommie" +delete-after: True +changes: + - image: "The \"One Lean, Mean, Cleaning Machine\" achievement now has its own icon." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-80993.yml b/html/changelogs/AutoChangeLog-pr-80993.yml new file mode 100644 index 00000000000..d12b8c5b1d7 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-80993.yml @@ -0,0 +1,4 @@ +author: "Ben10Omintrix" +delete-after: True +changes: + - bugfix: "fix a runtime when loading ghosts to a mulebot" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-81006.yml b/html/changelogs/AutoChangeLog-pr-81006.yml new file mode 100644 index 00000000000..ee0e3d328b5 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-81006.yml @@ -0,0 +1,4 @@ +author: "13spacemen" +delete-after: True +changes: + - bugfix: "Hub time should be correct again" \ No newline at end of file diff --git a/icons/ui_icons/achievements/achievements.dmi b/icons/ui_icons/achievements/achievements.dmi index 619ef96dda9..d8420439f4d 100644 Binary files a/icons/ui_icons/achievements/achievements.dmi and b/icons/ui_icons/achievements/achievements.dmi differ diff --git a/modular_nova/modules/automapper/code/area_spawn_subsystem.dm b/modular_nova/modules/automapper/code/area_spawn_subsystem.dm index f95548cb50c..358dc8c29fb 100644 --- a/modular_nova/modules/automapper/code/area_spawn_subsystem.dm +++ b/modular_nova/modules/automapper/code/area_spawn_subsystem.dm @@ -91,11 +91,12 @@ SUBSYSTEM_DEF(area_spawn) turf_list = area_turf_info["[mode]"] = list() // Get highest priority items - for(var/turf/iterating_turf as anything in area.get_contained_turfs()) - // Only retain turfs of the highest priority - var/priority = process_turf(iterating_turf, mode) - if(priority > 0) - LAZYADDASSOC(turf_list, "[priority]", list(iterating_turf)) + for(var/list/zlevel_turfs as anything in area.get_zlevel_turf_lists()) + for(var/turf/iterating_turf as anything in zlevel_turfs) + // Only retain turfs of the highest priority + var/priority = process_turf(iterating_turf, mode) + if(priority > 0) + LAZYADDASSOC(turf_list, "[priority]", list(iterating_turf)) // Sort the priorities descending return sortTim(turf_list, GLOBAL_PROC_REF(cmp_num_string_asc)) @@ -333,17 +334,18 @@ SUBSYSTEM_DEF(area_spawn) if(!found_area) continue - for(var/turf/candidate_turf as anything in found_area.get_contained_turfs()) - // Don't spawn if there's already a desired_atom here. - if(is_type_on_turf(candidate_turf, desired_atom)) - continue + for(var/list/zlevel_turfs as anything in found_area.get_zlevel_turf_lists()) + for(var/turf/candidate_turf as anything in zlevel_turfs) + // Don't spawn if there's already a desired_atom here. + if(is_type_on_turf(candidate_turf, desired_atom)) + continue - for(var/over_atom_type in over_atoms) - // Spawn on the first one we find in the turf and stop. - if(is_type_on_turf(candidate_turf, over_atom_type)) - new desired_atom(candidate_turf) - // Break the over_atom_type loop. - break + for(var/over_atom_type in over_atoms) + // Spawn on the first one we find in the turf and stop. + if(is_type_on_turf(candidate_turf, over_atom_type)) + new desired_atom(candidate_turf) + // Break the over_atom_type loop. + break /obj/effect/turf_test name = "PASS" @@ -361,9 +363,10 @@ SUBSYSTEM_DEF(area_spawn) set name = "Test Area Spawner" set desc = "Show area spawner placement candidates as an overlay." - for(var/turf/area_turf as anything in area.get_contained_turfs()) - for(var/obj/effect/turf_test/old_test in area_turf) - qdel(old_test) + for(var/list/zlevel_turfs as anything in area.get_zlevel_turf_lists()) + for(var/turf/area_turf as anything in zlevel_turfs) + for(var/obj/effect/turf_test/old_test in area_turf) + qdel(old_test) SSarea_spawn.clear_cache() for(var/mode in 0 to AREA_SPAWN_MODE_COUNT - 1) diff --git a/modular_nova/modules/clock_cult/code/structures/technologists_lectern.dm b/modular_nova/modules/clock_cult/code/structures/technologists_lectern.dm index fbbb8de5e4f..11759912286 100644 --- a/modular_nova/modules/clock_cult/code/structures/technologists_lectern.dm +++ b/modular_nova/modules/clock_cult/code/structures/technologists_lectern.dm @@ -428,10 +428,11 @@ apc_loop: for(var/obj/machinery/power/apc/controller as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/power/apc)) var/area/apc_area = get_area(controller) // make sure that no "critical" APCs lose their power (SM, namely) - for(var/turf/turf as anything in apc_area.get_contained_turfs()) - for(var/obj/machinery/depowered_machinery in turf) - if(depowered_machinery.critical_machine) - continue apc_loop + for(var/list/zlevel_turfs as anything in apc_area.get_zlevel_turf_lists()) + for(var/turf/turf as anything in zlevel_turfs) + for(var/obj/machinery/depowered_machinery in turf) + if(depowered_machinery.critical_machine) + continue apc_loop controller.cell?.charge = 0 diff --git a/modular_nova/modules/decay_subsystem/code/decaySS.dm b/modular_nova/modules/decay_subsystem/code/decaySS.dm index c3b59c479c0..d2c141f8b26 100644 --- a/modular_nova/modules/decay_subsystem/code/decaySS.dm +++ b/modular_nova/modules/decay_subsystem/code/decaySS.dm @@ -56,10 +56,11 @@ SUBSYSTEM_DEF(decay) possible_areas += iterating_area // Now add the turfs - for(var/turf/iterating_turf as anything in iterating_area.get_contained_turfs()) - if(!(iterating_turf.flags_1 & CAN_BE_DIRTY_1)) - continue - possible_turfs += iterating_turf + for(var/list/zlevel_turfs as anything in iterating_area.get_zlevel_turf_lists()) + for(var/turf/iterating_turf as anything in zlevel_turfs) + if(!(iterating_turf.flags_1 & CAN_BE_DIRTY_1)) + continue + possible_turfs += iterating_turf if(!possible_turfs) CRASH("SSDecay had no possible turfs to use!") diff --git a/modular_nova/modules/mold/code/mold_event.dm b/modular_nova/modules/mold/code/mold_event.dm index 7c8f32caff0..8c97b8328b0 100644 --- a/modular_nova/modules/mold/code/mold_event.dm +++ b/modular_nova/modules/mold/code/mold_event.dm @@ -48,17 +48,18 @@ if(!is_type_in_typecache(checked_area, possible_spawn_areas)) continue - for(var/turf/open/floor in checked_area.get_contained_turfs()) - if(isopenspaceturf(floor)) - continue + for(var/list/zlevel_turfs as anything in checked_area.get_zlevel_turf_lists()) + for(var/turf/open/floor in zlevel_turfs) + if(isopenspaceturf(floor)) + continue - if(!floor.Enter(test_resin)) - continue + if(!floor.Enter(test_resin)) + continue - if(locate(/turf/closed) in range(2, floor)) - continue + if(locate(/turf/closed) in range(2, floor)) + continue - turfs += floor + turfs += floor qdel(test_resin)