[MIRROR] Builds logic that manages turfs contained inside an area [MDB IGNORE] (#17379)

* Builds logic that manages turfs contained inside an area

* Mirror Conflict

* Modular!

Co-authored-by: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com>
Co-authored-by: Funce <funce.973@gmail.com>
Co-authored-by: tastyfish <crazychris32@gmail.com>
This commit is contained in:
SkyratBot
2022-11-16 14:42:22 -05:00
committed by GitHub
co-authored by LemonInTheDark Funce tastyfish
parent bd4e73411d
commit 24eb8217c0
45 changed files with 299 additions and 143 deletions
+3
View File
@@ -22,6 +22,9 @@
///Returns all turfs in a zlevel
#define Z_TURFS(ZLEVEL) block(locate(1,1,ZLEVEL), locate(world.maxx, world.maxy, ZLEVEL))
///Returns all currently loaded turfs
#define ALL_TURFS(...) block(locate(1, 1, 1), locate(world.maxx, world.maxy, world.maxz))
#define TURF_FROM_COORDS_LIST(List) (locate(List[1], List[2], List[3]))
/// The pipes, disposals, and wires are hidden
+28 -22
View File
@@ -123,7 +123,9 @@ GLOBAL_LIST_INIT(typecache_powerfailure_safe_areas, typecacheof(/area/station/en
for(var/i in 1 to length(turfs))
var/turf/thing = turfs[i]
var/area/old_area = thing.loc
old_area.turfs_to_uncontain += thing
newA.contents += thing
newA.contained_turfs += thing
thing.transfer_area_lighting(old_area, newA)
newA.reg_in_areas_in_z()
@@ -143,18 +145,14 @@ GLOBAL_LIST_INIT(typecache_powerfailure_safe_areas, typecacheof(/area/station/en
#undef BP_MAX_ROOM_SIZE
//Repopulates sortedAreas list
/proc/repopulate_sorted_areas()
GLOB.sortedAreas = list()
/proc/require_area_resort()
GLOB.sortedAreas = null
for(var/area/A in world)
GLOB.sortedAreas.Add(A)
sortTim(GLOB.sortedAreas, GLOBAL_PROC_REF(cmp_name_asc))
/area/proc/addSorted()
GLOB.sortedAreas.Add(src)
sortTim(GLOB.sortedAreas, GLOBAL_PROC_REF(cmp_name_asc))
/// Returns a sorted version of GLOB.areas, by name
/proc/get_sorted_areas()
if(!GLOB.sortedAreas)
GLOB.sortedAreas = sortTim(GLOB.areas.Copy(), /proc/cmp_name_asc)
return GLOB.sortedAreas
//Takes: Area type as a text string from a variable.
//Returns: Instance for the area in the world.
@@ -177,11 +175,11 @@ GLOBAL_LIST_INIT(typecache_powerfailure_safe_areas, typecacheof(/area/station/en
var/list/areas = list()
if(subtypes)
var/list/cache = typecacheof(areatype)
for(var/area/area_to_check as anything in GLOB.sortedAreas)
for(var/area/area_to_check as anything in GLOB.areas)
if(cache[area_to_check.type])
areas += area_to_check
else
for(var/area/area_to_check as anything in GLOB.sortedAreas)
for(var/area/area_to_check as anything in GLOB.areas)
if(area_to_check.type == areatype)
areas += area_to_check
return areas
@@ -204,25 +202,33 @@ GLOBAL_LIST_INIT(typecache_powerfailure_safe_areas, typecacheof(/area/station/en
areatype = areatemp.type
else if(!ispath(areatype))
return null
var/list/turfs = list()
// Pull out the areas
var/list/areas_to_pull = list()
if(subtypes)
var/list/cache = typecacheof(areatype)
for(var/area/area_to_check as anything in GLOB.sortedAreas)
for(var/area/area_to_check as anything in GLOB.areas)
if(!cache[area_to_check.type])
continue
for(var/turf/turf_in_area in area_to_check)
if(target_z == 0 || target_z == turf_in_area.z)
turfs += turf_in_area
areas_to_pull += area_to_check
else
for(var/area/area_to_check as anything in GLOB.sortedAreas)
for(var/area/area_to_check as anything in GLOB.areas)
if(area_to_check.type != areatype)
continue
for(var/turf/turf_in_area in area_to_check)
if(target_z == 0 || target_z == turf_in_area.z)
areas_to_pull += area_to_check
// 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
else
for(var/turf/turf_in_area as anything in our_turfs)
if(target_z == turf_in_area.z)
turfs += turf_in_area
return turfs
///Takes: list of area types
///Returns: all mobs that are in an area type
/proc/mobs_in_area_type(list/area/checked_areas)
+6 -2
View File
@@ -119,10 +119,14 @@ GLOBAL_LIST_EMPTY(emergencyresponseteamspawn)
GLOBAL_LIST_EMPTY(ruin_landmarks)
GLOBAL_LIST_EMPTY(bar_areas)
//away missions
/// Away missions
GLOBAL_LIST_EMPTY(vr_spawnpoints)
//used by jump-to-area etc. Updated by area/updateName()
/// Just a list of all the area objects in the game
/// Note, areas can have duplicate types
GLOBAL_LIST_EMPTY(areas)
/// Used by jump-to-area etc. Updated by area/updateName()
/// If this is null, it needs to be recalculated. Use get_sorted_areas() as a getter please
GLOBAL_LIST_EMPTY(sortedAreas)
/// An association from typepath to area instance. Only includes areas with `unique` set.
GLOBAL_LIST_EMPTY_TYPED(areas_by_type, /area)
+1 -2
View File
@@ -523,7 +523,6 @@ SUBSYSTEM_DEF(air)
queued_for_activation.Cut()
/datum/controller/subsystem/air/proc/setup_allturfs()
var/list/turfs_to_init = block(locate(1, 1, 1), locate(world.maxx, world.maxy, world.maxz))
var/list/active_turfs = src.active_turfs
times_fired++
@@ -537,7 +536,7 @@ SUBSYSTEM_DEF(air)
active_turfs.Cut()
var/time = 0
for(var/turf/T as anything in turfs_to_init)
for(var/turf/T as anything in ALL_TURFS())
if (!T.init_air)
continue
// We pass the tick as the current step so if we sleep the step changes
@@ -0,0 +1,55 @@
#define ALLOWED_LOOSE_TURFS 500
/**
* 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
* as a consequence of repeated changes in area in a space
* They additionally may not always resolve often enough to avoid memory leaks
* This is annoying, so lets keep an eye on them and cut them down to size if needed
*/
SUBSYSTEM_DEF(area_contents)
name = "Area Contents"
flags = SS_NO_INIT
runlevels = RUNLEVEL_LOBBY|RUNLEVELS_DEFAULT
var/list/currentrun
var/list/area/marked_for_clearing = list()
/datum/controller/subsystem/area_contents/stat_entry(msg)
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)
msg = "A:[length(currentrun)] MR:[length(marked_for_clearing)] TC:[total_to_clear] CF:[total_clearing_from]"
return ..()
/datum/controller/subsystem/area_contents/fire(resumed)
if(!resumed)
currentrun = GLOB.areas.Copy()
while(length(currentrun))
var/area/test = currentrun[length(currentrun)]
if(length(test.turfs_to_uncontain) > ALLOWED_LOOSE_TURFS)
marked_for_clearing |= test
currentrun.len--
if(MC_TICK_CHECK)
return
// Alright, if we've done a scan on all our areas, it's time to knock the existing ones down to size
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()
marked_for_clearing.len--
+26 -7
View File
@@ -115,7 +115,7 @@ SUBSYSTEM_DEF(mapping)
initialize_biomes()
loadWorld()
determine_fake_sale()
repopulate_sorted_areas()
require_area_resort()
process_teleport_locs() //Sets up the wizard teleport locations
preloadTemplates()
@@ -142,7 +142,7 @@ SUBSYSTEM_DEF(mapping)
run_map_generation()
// Add the transit level
transit = add_new_zlevel("Transit/Reserved", list(ZTRAIT_RESERVED = TRUE))
repopulate_sorted_areas()
require_area_resort()
// Set up Z-level transitions.
setup_map_transitions()
generate_station_area_list()
@@ -155,6 +155,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/lists_to_reserve = src.lists_to_reserve
var/index = 0
while(index < length(lists_to_reserve))
@@ -168,8 +169,11 @@ SUBSYSTEM_DEF(mapping)
T.empty(RESERVED_TURF_TYPE, RESERVED_TURF_TYPE, null, TRUE)
LAZYINITLIST(unused_turfs["[T.z]"])
unused_turfs["[T.z]"] |= T
var/area/old_area = T.loc
old_area.turfs_to_uncontain += T
T.flags_1 |= UNUSED_RESERVATION_TURF
world_contents += T
world_turf_contents += T
packet.len--
packetlen = length(packet)
@@ -362,7 +366,7 @@ Used by the AI doomsday and the self-destruct nuke.
var/start_z = world.maxz + 1
var/i = 0
for (var/level in traits)
add_new_zlevel("[name][i ? " [i + 1]" : ""]", level)
add_new_zlevel("[name][i ? " [i + 1]" : ""]", level, contain_turfs = FALSE)
++i
SSautomapper.preload_templates_from_toml(files) // SKYRAT EDIT ADDITION - We need to load our templates AFTER the Z level exists, otherwise, there is no z level to preload.
@@ -372,7 +376,7 @@ Used by the AI doomsday and the self-destruct nuke.
for (var/P in parsed_maps)
var/datum/parsed_map/pm = P
pm.turf_blacklist = turf_blacklist // SKYRAT EDIT ADDITION - apply blacklist
if (!pm.load(1, 1, start_z + parsed_maps[P], no_changeturf = TRUE))
if (!pm.load(1, 1, start_z + parsed_maps[P], no_changeturf = TRUE, new_z = TRUE))
errorList |= pm.original_path
// SKYRAT EDIT ADDITION BEGIN - We need to load our templates from cache after our space has been carved out.
if(!LAZYLEN(errorList))
@@ -431,7 +435,7 @@ Used by the AI doomsday and the self-destruct nuke.
GLOBAL_LIST_EMPTY(the_station_areas)
/datum/controller/subsystem/mapping/proc/generate_station_area_list()
for(var/area/station/station_area in world)
for(var/area/station/station_area in GLOB.areas)
if (!(station_area.area_flags & UNIQUE_AREA))
continue
if (is_station_level(station_area.z))
@@ -441,7 +445,7 @@ GLOBAL_LIST_EMPTY(the_station_areas)
log_world("ERROR: Station areas list failed to generate!")
/datum/controller/subsystem/mapping/proc/run_map_generation()
for(var/area/A in world)
for(var/area/A as anything in GLOB.areas)
A.RunGeneration()
/datum/controller/subsystem/mapping/proc/maprotate()
@@ -724,7 +728,7 @@ GLOBAL_LIST_EMPTY(the_station_areas)
/// 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)
/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
@@ -743,11 +747,26 @@ GLOBAL_LIST_EMPTY(the_station_areas)
if(below_offset)
update_plane_tracking(new_z)
if(contain_turfs)
build_area_turfs(z_value, filled_with_space)
// And finally, misc global generation
// We'll have to update this if offsets change, because we load lowest z to highest z
generate_lighting_appearance_by_z(z_value)
/datum/controller/subsystem/mapping/proc/build_area_turfs(z_level, space_guaranteed)
// If we know this is filled with default tiles, we can use the default area
// Faster
if(space_guaranteed)
var/area/global_area = GLOB.areas_by_type[world.area]
global_area.contained_turfs += 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
/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
// Yes this will cause infinite loops if our templating is fucked. Fuck off
@@ -65,7 +65,7 @@ SUBSYSTEM_DEF(networks)
/datum/controller/subsystem/networks/Initialize()
station_network.register_map_supremecy() // sigh
assign_areas_root_ids(GLOB.sortedAreas) // setup area names before Initialize
assign_areas_root_ids(get_sorted_areas()) // setup area names before Initialize
station_network.build_software_lists()
syndie_network.build_software_lists()
+3
View File
@@ -619,9 +619,12 @@ SUBSYSTEM_DEF(shuttle)
var/turf/midpoint = locate(transit_x, transit_y, bottomleft.z)
if(!midpoint)
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
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]"
+35 -10
View File
@@ -13,6 +13,15 @@
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)
/// 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
/// 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()
var/area_flags = VALID_TERRITORY | BLOBS_ALLOWED | UNIQUE_AREA | CULT_PERMITTED
///Do we have an active fire alarm?
@@ -127,20 +136,16 @@ GLOBAL_LIST_EMPTY(teleportlocs)
* The returned list of turfs is sorted by name
*/
/proc/process_teleport_locs()
for(var/V in GLOB.sortedAreas)
var/area/AR = V
for(var/area/AR as anything in get_sorted_areas())
if(istype(AR, /area/shuttle) || AR.area_flags & NOTELEPORT)
continue
if(GLOB.teleportlocs[AR.name])
continue
if (!AR.contents.len)
if (!AR.has_contained_turfs())
continue
var/turf/picked = AR.contents[1]
if (picked && is_station_level(picked.z))
if (is_station_level(AR.z))
GLOB.teleportlocs[AR.name] = AR
sortTim(GLOB.teleportlocs, GLOBAL_PROC_REF(cmp_text_asc))
/**
* Called when an area loads
*
@@ -151,6 +156,7 @@ GLOBAL_LIST_EMPTY(teleportlocs)
// rather than waiting for atoms to initialize.
if (area_flags & UNIQUE_AREA)
GLOB.areas_by_type[type] = src
GLOB.areas += src
power_usage = new /list(AREA_USAGE_LEN) // Some atoms would like to use power in Initialize()
alarm_manager = new(src) // just in case
return ..()
@@ -219,6 +225,24 @@ GLOBAL_LIST_EMPTY(teleportlocs)
turfs += T
map_generator.generate_terrain(turfs, src)
/area/proc/get_contained_turfs()
if(length(turfs_to_uncontain))
cannonize_contained_turfs()
return contained_turfs
/// Ensures that the contained_turfs list properly represents the turfs actually inside us
/area/proc/cannonize_contained_turfs()
// 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()
/// Returns TRUE if we have contained turfs, FALSE otherwise
/area/proc/has_contained_turfs()
return length(contained_turfs) - length(turfs_to_uncontain) > 0
/**
* Register this area as belonging to a z level
@@ -226,7 +250,7 @@ GLOBAL_LIST_EMPTY(teleportlocs)
* Ensures the item is added to the SSmapping.areas_in_z list for this z
*/
/area/proc/reg_in_areas_in_z()
if(!length(contents))
if(!has_contained_turfs())
return
var/list/areas_in_z = SSmapping.areas_in_z
update_areasize()
@@ -249,6 +273,7 @@ GLOBAL_LIST_EMPTY(teleportlocs)
if(GLOB.areas_by_type[type] == src)
GLOB.areas_by_type[type] = null
GLOB.sortedAreas -= src
GLOB.areas -= src
STOP_PROCESSING(SSobj, src)
QDEL_NULL(alarm_manager)
return ..()
@@ -472,7 +497,7 @@ GLOBAL_LIST_EMPTY(teleportlocs)
always_unpowered = FALSE
area_flags &= ~VALID_TERRITORY
area_flags &= ~BLOBS_ALLOWED
addSorted()
require_area_resort()
/**
* Set the area size of the area
*
@@ -483,7 +508,7 @@ GLOBAL_LIST_EMPTY(teleportlocs)
if(outdoors)
return FALSE
areasize = 0
for(var/turf/open/T in contents)
for(var/turf/open/T in get_contained_turfs())
areasize++
/**
+1 -1
View File
@@ -973,7 +973,7 @@ GLOBAL_LIST_EMPTY(possible_items_special)
/datum/objective/contract/proc/generate_dropoff()
var/found = FALSE
while (!found)
var/area/dropoff_area = pick(GLOB.sortedAreas)
var/area/dropoff_area = pick(GLOB.areas)
if(dropoff_area && (dropoff_area.type in GLOB.the_station_areas) && !dropoff_area.outdoors)
dropoff = dropoff_area
found = TRUE
+4 -3
View File
@@ -1,4 +1,4 @@
/client/proc/jumptoarea(area/A in GLOB.sortedAreas)
/client/proc/jumptoarea(area/A in get_sorted_areas())
set name = "Jump to Area"
set desc = "Area to jump to"
set category = "Admin.Game"
@@ -159,10 +159,11 @@
if(!src.holder)
to_chat(src, "Only administrators may use this command.", confidential = TRUE)
return
if(!length(GLOB.sortedAreas))
var/list/sorted_areas = get_sorted_areas()
if(!length(sorted_areas))
to_chat(src, "No areas found.", confidential = TRUE)
return
var/area/target_area = tgui_input_list(src, "Pick an area", "Send Mob", GLOB.sortedAreas)
var/area/target_area = tgui_input_list(src, "Pick an area", "Send Mob", sorted_areas)
if(isnull(target_area))
return
if(!istype(target_area))
+1 -1
View File
@@ -286,7 +286,7 @@
message_admins(span_adminnotice("[key_name_admin(usr)] used the Test Areas debug command checking [log_message]."))
log_admin("[key_name(usr)] used the Test Areas debug command checking [log_message].")
for(var/area/A in world)
for(var/area/A as anything in GLOB.areas)
if(on_station)
var/list/area_turfs = get_area_turfs(A.type)
if (!length(area_turfs))
+1 -1
View File
@@ -180,7 +180,7 @@ GLOBAL_LIST_EMPTY(blob_nodes)
else
L.fully_heal(admin_revive = FALSE)
for(var/area/A in GLOB.sortedAreas)
for(var/area/A in GLOB.areas)
if(!(A.type in GLOB.the_station_areas))
continue
if(!(A.area_flags & BLOBS_ALLOWED))
+1 -1
View File
@@ -424,7 +424,7 @@
..()
var/sanity = 0
while(summon_spots.len < SUMMON_POSSIBILITIES && sanity < 100)
var/area/summon_area = pick(GLOB.sortedAreas - summon_spots)
var/area/summon_area = pick(GLOB.areas - summon_spots)
if(summon_area && is_station_level(summon_area.z) && (summon_area.area_flags & VALID_TERRITORY))
summon_spots += summon_area
sanity++
@@ -77,7 +77,7 @@
//Explosive plant, the bomb will register its completion on priming
var/datum/objective/plant_explosive/bombobjective = new /datum/objective/plant_explosive()
for(var/sanity in 1 to 100) // 100 checks at most.
var/area/selected_area = pick(GLOB.sortedAreas)
var/area/selected_area = pick(GLOB.areas)
if(!is_station_level(selected_area.z) || !(selected_area.area_flags & VALID_TERRITORY))
continue
bombobjective.detonation_location = selected_area
+2 -2
View File
@@ -81,9 +81,9 @@
else
var/mob/user_mob = user
holder = user_mob.client //if its a mob, assign the mob's client to holder
bay = locate(/area/centcom/central_command_areas/supplypod/loading/one) in GLOB.sortedAreas //Locate the default bay (one) from the centcom map
bay = locate(/area/centcom/central_command_areas/supplypod/loading/one) in GLOB.areas //Locate the default bay (one) from the centcom map
bayNumber = bay.loading_id //Used as quick reference to what bay we're taking items from
var/area/pod_storage_area = locate(/area/centcom/central_command_areas/supplypod/pod_storage) in GLOB.sortedAreas
var/area/pod_storage_area = locate(/area/centcom/central_command_areas/supplypod/pod_storage) in GLOB.areas
temp_pod = new(pick(get_area_turfs(pod_storage_area))) //Create a new temp_pod in the podStorage area on centcom (so users are free to look at it and change other variables if needed)
orderedArea = createOrderedArea(bay) //Order all the turfs in the selected bay (top left to bottom right) to a single list. Used for the "ordered" mode (launchChoice = 1)
selector = new(null, holder.mob)
+2 -2
View File
@@ -191,7 +191,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.contents)//uses default landing zone
for(var/turf/open/floor/T in landingzone.get_contained_turfs())//uses default landing zone
if(T.is_blocked_turf())
continue
LAZYADD(empty_turfs, T)
@@ -210,7 +210,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.contents)
for(var/turf/open/floor/T in landingzone.get_contained_turfs())
if(T.is_blocked_turf())
continue
LAZYADD(empty_turfs, T)
@@ -99,9 +99,8 @@
if(!port)
return
var/list/shuttle_areas = port.shuttle_areas
for(var/r in shuttle_areas)
var/area/region = r
for(var/turf/place in region.contents)
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
@@ -185,7 +184,7 @@
if(open.blocks_air)
continue
var/datum/gas_mixture/environment = open.return_air()
var/temp = round(environment.return_temperature())
var/temp = round(environment.return_temperature())
var/image/pic = image('icons/turf/overlays.dmi', open, "greyOverlay", ABOVE_ALL_MOB_LAYER)
// Lower than TEMP_SHADE_CYAN should be deep blue
switch(temp)
@@ -7,7 +7,7 @@
/datum/anomaly_placer/proc/findValidArea()
if(!allowed_areas)
generateAllowedAreas()
var/list/possible_areas = typecache_filter_list(GLOB.sortedAreas,allowed_areas)
var/list/possible_areas = typecache_filter_list(GLOB.areas, allowed_areas)
if (!length(possible_areas))
CRASH("No valid areas for anomaly found.")
+9 -11
View File
@@ -29,13 +29,12 @@
M.playsound_local(M, 'sound/ambience/aurora_caelus.ogg', 20, FALSE, pressure_affected = FALSE)
/datum/round_event/aurora_caelus/start()
for(var/area in GLOB.sortedAreas)
var/area/affected_area = area
for(var/area/affected_area as anything in GLOB.areas)
if(affected_area.area_flags & AREA_USES_STARLIGHT)
for(var/turf/open/space/spess in affected_area)
for(var/turf/open/space/spess in affected_area.get_contained_turfs())
spess.set_light(spess.light_range * 3, spess.light_power * 0.5)
if(istype(affected_area, /area/station/service/kitchen))
for(var/turf/open/kitchen in affected_area)
for(var/turf/open/kitchen in affected_area.get_contained_turfs())
kitchen.set_light(1, 0.75)
if(!prob(1) && !check_holidays(APRIL_FOOLS))
continue
@@ -56,23 +55,22 @@
if(activeFor % 5 == 0)
aurora_progress++
var/aurora_color = aurora_colors[aurora_progress]
for(var/area in GLOB.sortedAreas)
var/area/affected_area = area
for(var/area/affected_area as anything in GLOB.areas)
if(affected_area.area_flags & AREA_USES_STARLIGHT)
for(var/turf/open/space/spess as anything in affected_area)
for(var/turf/open/space/spess in affected_area.get_contained_turfs())
spess.set_light(l_color = aurora_color)
if(istype(affected_area, /area/station/service/kitchen))
for(var/turf/open/kitchen_floor in affected_area)
for(var/turf/open/kitchen_floor in affected_area.get_contained_turfs())
kitchen_floor.set_light(l_color = aurora_color)
/datum/round_event/aurora_caelus/end()
for(var/area in GLOB.sortedAreas)
for(var/area in GLOB.areas)
var/area/affected_area = area
if(affected_area.area_flags & AREA_USES_STARLIGHT)
for(var/turf/open/space/spess in affected_area)
for(var/turf/open/space/spess in affected_area.get_contained_turfs())
fade_to_black(spess)
if(istype(affected_area, /area/station/service/kitchen))
for(var/turf/open/superturfentent in affected_area)
for(var/turf/open/superturfentent in affected_area.get_contained_turfs())
fade_to_black(superturfentent)
priority_announce("The aurora caelus event is now ending. Starlight conditions will slowly return to normal. When this has concluded, please return to your workplace and continue work as normal. Have a pleasant shift, [station_name()], and thank you for watching with us.",
sound = 'sound/misc/notice2.ogg',
+1 -1
View File
@@ -25,7 +25,7 @@
severity = rand(1,3)
for(var/i in 1 to severity)
var/picked_area = pick_n_take(potential_areas)
for(var/area/A in world)
for(var/area/A as anything in GLOB.areas)
if(istype(A, picked_area))
areasToOpen += A
+2 -2
View File
@@ -64,8 +64,8 @@
var/obj/structure/spacevine/vine = new()
for(var/area/station/hallway/area in world)
for(var/turf/floor in area)
for(var/area/station/hallway/area in GLOB.areas)
for(var/turf/floor as anything in area.get_contained_turfs())
if(floor.Enter(vine))
turfs += floor
+2 -2
View File
@@ -56,7 +56,7 @@
if(ispath(pack_type, /datum/supply_pack))
SP = new pack_type
else // treat this as a supply pack id and resolving it with SSshuttle
SP = SSshuttle.supply_packs[pack_type]
SP = SSshuttle.supply_packs[pack_type]
var/obj/structure/closet/crate/crate = SP.generate(null)
if(crate) //empty supply packs are a thing! get memed on.
crate.locked = FALSE //Unlock secure crates
@@ -84,7 +84,7 @@
///Subtypes from the above that actually should explode.
var/static/list/unsafe_area_subtypes = typecacheof(list(/area/station/engineering/break_room))
allowed_areas = make_associative(GLOB.the_station_areas) - safe_area_types + unsafe_area_subtypes
var/list/possible_areas = typecache_filter_list(GLOB.sortedAreas,allowed_areas)
var/list/possible_areas = typecache_filter_list(GLOB.areas, allowed_areas)
if (length(possible_areas))
return pick(possible_areas)
+2 -2
View File
@@ -49,7 +49,7 @@
/area/proc/remove_base_lighting()
var/list/z_offsets = SSmapping.z_level_to_plane_offset
for(var/turf/T in src)
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])
cut_overlay(lighting_effects[1])
@@ -69,7 +69,7 @@
lighting_effects += lighting_effect
add_overlay(lighting_effects[1])
var/list/z_offsets = SSmapping.z_level_to_plane_offset
for(var/turf/T in src)
for(var/turf/T as anything in get_contained_turfs())
T.luminosity = 1
// This outside loop is EXTREMELY hot because it's run by space tiles. Don't want no part in that
// We will only add overlays to turfs not on the first z layer, because that's a significantly lesser portion
+2 -3
View File
@@ -1,11 +1,10 @@
/proc/create_all_lighting_objects()
for(var/area/A in world)
for(var/area/A as anything in GLOB.areas)
if(!A.static_lighting)
continue
// I hate this so much dude. why do areas not track their turfs lummyyyyyyy
for(var/turf/T in A)
for(var/turf/T as anything in A.get_contained_turfs())
if(T.always_lit)
continue
new/datum/lighting_object(T)
+4 -6
View File
@@ -133,14 +133,13 @@
var/x = round((world.maxx - width) * 0.5) + 1
var/y = round((world.maxy - height) * 0.5) + 1
var/datum/space_level/level = SSmapping.add_new_zlevel(name, secret ? ZTRAITS_AWAY_SECRET : ZTRAITS_AWAY)
var/datum/parsed_map/parsed = load_map(file(mappath), x, y, level.z_value, no_changeturf=(SSatoms.initialized == INITIALIZATION_INSSATOMS), placeOnTop=should_place_on_top)
var/datum/space_level/level = SSmapping.add_new_zlevel(name, secret ? ZTRAITS_AWAY_SECRET : ZTRAITS_AWAY, contain_turfs = FALSE)
var/datum/parsed_map/parsed = load_map(file(mappath), x, y, level.z_value, no_changeturf=(SSatoms.initialized == INITIALIZATION_INSSATOMS), placeOnTop=should_place_on_top, new_z = TRUE)
var/list/bounds = parsed.bounds
if(!bounds)
return FALSE
repopulate_sorted_areas()
require_area_resort()
//initialize things that are normally initialized after map load
initTemplateBounds(bounds)
smooth_zlevel(world.maxz)
@@ -181,8 +180,7 @@
if(!bounds)
return
if(!SSmapping.loading_ruins) //Will be done manually during mapping ss init
repopulate_sorted_areas()
require_area_resort()
//initialize things that are normally initialized after map load
initTemplateBounds(bounds)
+27 -18
View File
@@ -50,10 +50,10 @@
/// - `no_changeturf`: When true, [/turf/proc/AfterChange] won't be called on loaded turfs
/// - `x_lower`, `x_upper`, `y_lower`, `y_upper`: Coordinates (relative to the map) to crop to (Optional).
/// - `placeOnTop`: Whether to use [/turf/proc/PlaceOnTop] rather than [/turf/proc/ChangeTurf] (Optional).
/proc/load_map(dmm_file as file, x_offset as num, y_offset as num, z_offset as num, cropMap as num, measureOnly as num, no_changeturf as num, x_lower = -INFINITY as num, x_upper = INFINITY as num, y_lower = -INFINITY as num, y_upper = INFINITY as num, placeOnTop = FALSE as num)
/proc/load_map(dmm_file as file, x_offset as num, y_offset as num, z_offset as num, cropMap as num, measureOnly as num, no_changeturf as num, x_lower = -INFINITY as num, x_upper = INFINITY as num, y_lower = -INFINITY as num, y_upper = INFINITY as num, placeOnTop = FALSE as num, new_z)
var/datum/parsed_map/parsed = new(dmm_file, x_lower, x_upper, y_lower, y_upper, measureOnly)
if(parsed.bounds && !measureOnly)
parsed.load(x_offset, y_offset, z_offset, cropMap, no_changeturf, x_lower, x_upper, y_lower, y_upper, placeOnTop)
parsed.load(x_offset, y_offset, z_offset, cropMap, no_changeturf, x_lower, x_upper, y_lower, y_upper, placeOnTop, new_z = new_z)
return parsed
/// Parse a map, possibly cropping it.
@@ -157,10 +157,10 @@
src.key_len = key_len
/// Load the parsed map into the world. See [/proc/load_map] for arguments.
/datum/parsed_map/proc/load(x_offset, y_offset, z_offset, cropMap, no_changeturf, x_lower, x_upper, y_lower, y_upper, placeOnTop, whitelist = FALSE)
/datum/parsed_map/proc/load(x_offset, y_offset, z_offset, cropMap, no_changeturf, x_lower, x_upper, y_lower, y_upper, placeOnTop, whitelist = FALSE, new_z)
//How I wish for RAII
Master.StartLoadingMap()
. = _load_impl(x_offset, y_offset, z_offset, cropMap, no_changeturf, x_lower, x_upper, y_lower, y_upper, placeOnTop)
. = _load_impl(x_offset, y_offset, z_offset, cropMap, no_changeturf, x_lower, x_upper, y_lower, y_upper, placeOnTop, new_z)
Master.StopLoadingMap()
@@ -171,7 +171,7 @@
SSatoms.map_loader_begin(); \
}
// Do not call except via load() above.
/datum/parsed_map/proc/_load_impl(x_offset = 1, y_offset = 1, z_offset = world.maxz + 1, cropMap = FALSE, no_changeturf = FALSE, x_lower = -INFINITY, x_upper = INFINITY, y_lower = -INFINITY, y_upper = INFINITY, placeOnTop = FALSE)
/datum/parsed_map/proc/_load_impl(x_offset = 1, y_offset = 1, z_offset = world.maxz + 1, cropMap = FALSE, no_changeturf = FALSE, x_lower = -INFINITY, x_upper = INFINITY, y_lower = -INFINITY, y_upper = INFINITY, placeOnTop = FALSE, new_z = FALSE)
PRIVATE_PROC(TRUE)
var/list/modelCache = build_cache(no_changeturf)
var/space_key = modelCache[SPACE_KEY]
@@ -288,7 +288,7 @@
if(!cache)
SSatoms.map_loader_stop()
CRASH("Undefined model key in DMM: [line]")
build_coordinate(cache, locate(true_xcrd, ycrd, zcrd), no_afterchange, placeOnTop)
build_coordinate(cache, locate(true_xcrd, ycrd, zcrd), no_afterchange, placeOnTop, new_z)
// only bother with bounds that actually exist
if(!first_found)
@@ -320,7 +320,7 @@
if(!cache)
SSatoms.map_loader_stop()
CRASH("Undefined model key in DMM: [model_key]")
build_coordinate(cache, locate(xcrd, ycrd, zcrd), no_afterchange, placeOnTop)
build_coordinate(cache, locate(xcrd, ycrd, zcrd), no_afterchange, placeOnTop, new_z)
// only bother with bounds that actually exist
if(!first_found)
@@ -347,6 +347,10 @@
//we do this after we load everything in. if we don't; we'll have weird atmos bugs regarding atmos adjacent turfs
T.AfterChange(CHANGETURF_IGNORE_AIR)
if(new_z)
for(var/z_index in bounds[MAP_MINZ] to bounds[MAP_MAXZ])
SSmapping.build_area_turfs(z_index)
if(has_expanded_world_maxx || has_expanded_world_maxy)
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_EXPANDED_WORLD_BOUNDS, has_expanded_world_maxx, has_expanded_world_maxy)
@@ -437,7 +441,7 @@ GLOBAL_LIST_EMPTY(map_model_default)
.[model_key] = list(members, members_attributes)
/datum/parsed_map/proc/build_coordinate(list/model, turf/crds, no_changeturf as num, placeOnTop as num)
/datum/parsed_map/proc/build_coordinate(list/model, turf/crds, no_changeturf as num, placeOnTop as num, new_z)
// If we don't have a turf, nothing we will do next will actually acomplish anything, so just go back
// Note, this would actually drop area vvs in the tile, but like, why tho
if(!crds)
@@ -458,29 +462,34 @@ GLOBAL_LIST_EMPTY(map_model_default)
//The next part of the code assumes there's ALWAYS an /area AND a /turf on a given tile
//first instance the /area and remove it from the members list
index = members.len
var/atom/instance
if(members[index] != /area/template_noop)
var/area/area_instance
if(members_attributes[index] != default_list)
world.preloader_setup(members_attributes[index], members[index])//preloader for assigning set variables on atom creation
instance = loaded_areas[members[index]]
if(!instance)
area_instance = loaded_areas[members[index]]
if(!area_instance)
var/area_type = members[index]
// If this parsed map doesn't have that area already, we check the global cache
instance = GLOB.areas_by_type[area_type]
area_instance = GLOB.areas_by_type[area_type]
// If the global list DOESN'T have this area it's either not a unique area, or it just hasn't been created yet
if (!instance)
instance = new area_type(null)
if(!instance)
if (!area_instance)
area_instance = new area_type(null)
if(!area_instance)
CRASH("[area_type] failed to be new'd, what'd you do?")
loaded_areas[area_type] = instance
loaded_areas[area_type] = area_instance
instance.contents.Add(crds)
if(!new_z)
var/area/old_area = crds.loc
old_area.turfs_to_uncontain += crds
area_instance.contained_turfs.Add(crds)
area_instance.contents.Add(crds)
if(GLOB.use_preloader)
world.preloader_load(instance)
world.preloader_load(area_instance)
// Index right before /area is /turf
index--
var/atom/instance
//then instance the /turf
//NOTE: this used to place any turfs before the last "underneath" it using .appearance and underlays
//We don't actually use this, and all it did was cost cpu, so we don't do this anymore
@@ -16,10 +16,10 @@
for (var/I in 1 to default_map_traits.len)
var/list/features = default_map_traits[I]
var/datum/space_level/S = new(I, features[DL_NAME], features[DL_TRAITS])
manage_z_level(S)
manage_z_level(S, filled_with_space = FALSE)
generate_z_level_linkages() // Default Zs don't use add_new_zlevel() so they don't automatically generate z-linkages.
/datum/controller/subsystem/mapping/proc/add_new_zlevel(name, traits = list(), z_type = /datum/space_level)
/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
@@ -28,7 +28,7 @@
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)
manage_z_level(S, filled_with_space = TRUE, contain_turfs = contain_turfs)
generate_linkages_for_z_level(new_z)
calculate_z_level_gravity(new_z)
adding_new_zlevel = FALSE
+1 -2
View File
@@ -465,8 +465,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
to_chat(usr, span_warning("Not when you're not dead!"))
return
var/list/filtered = list()
for(var/V in GLOB.sortedAreas)
var/area/A = V
for(var/area/A as anything in get_sorted_areas())
if(!(A.area_flags & HIDDEN_AREA))
filtered += A
var/area/thearea = tgui_input_list(usr, "Area to jump to", "BOOYEA", filtered)
@@ -34,7 +34,7 @@
var/list/obj/structure/cable/cables = list()
var/list/atom/atoms = list()
repopulate_sorted_areas()
require_area_resort()
for(var/L in block(locate(bounds[MAP_MINX], bounds[MAP_MINY], SSmapping.station_start),
locate(bounds[MAP_MAXX], bounds[MAP_MAXY], z_offset - 1)))
+1 -1
View File
@@ -656,7 +656,7 @@
/datum/religion_rites/declare_arena/perform_rite(mob/living/user, atom/religious_tool)
var/list/filtered = list()
for(var/area/unfiltered_area as anything in GLOB.sortedAreas)
for(var/area/unfiltered_area as anything in get_sorted_areas())
if(istype(unfiltered_area, /area/centcom)) //youuu dont need thaaat
continue
if(!(unfiltered_area.area_flags & HIDDEN_AREA))
@@ -151,19 +151,21 @@ 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 world)
for(var/obj/machinery/door/airlock/D in A)
D.emergency = TRUE
D.update_icon(ALL, 0)
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)
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 world)
for(var/obj/machinery/door/airlock/D in A)
D.emergency = FALSE
D.update_icon(ALL, 0)
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)
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"))
+1 -1
View File
@@ -36,7 +36,7 @@
areas = list()
var/list/new_latejoin = list()
for(var/area/shuttle/arrival/A in GLOB.sortedAreas)
for(var/area/shuttle/arrival/A in GLOB.areas)
for(var/obj/structure/chair/C in A)
new_latejoin += C
if(!console)
+3 -3
View File
@@ -481,7 +481,7 @@
if(time_left <= 50 && !sound_played) //4 seconds left:REV UP THOSE ENGINES BOYS. - should sync up with the launch
sound_played = 1 //Only rev them up once.
var/list/areas = list()
for(var/area/shuttle/escape/E in GLOB.sortedAreas)
for(var/area/shuttle/escape/E in GLOB.areas)
areas += E
hyperspace_sound(HYPERSPACE_WARMUP, areas)
@@ -493,7 +493,7 @@
//now move the actual emergency shuttle to its transit dock
var/list/areas = list()
for(var/area/shuttle/escape/E in GLOB.sortedAreas)
for(var/area/shuttle/escape/E in GLOB.areas)
areas += E
hyperspace_sound(HYPERSPACE_LAUNCH, areas)
enterTransit()
@@ -512,7 +512,7 @@
if(SHUTTLE_ESCAPE)
if(sound_played && time_left <= HYPERSPACE_END_TIME)
var/list/areas = list()
for(var/area/shuttle/escape/E in GLOB.sortedAreas)
for(var/area/shuttle/escape/E in GLOB.areas)
areas += E
hyperspace_sound(HYPERSPACE_END, areas)
if(time_left <= PARALLAX_LOOP_TIME)
+4
View File
@@ -171,7 +171,9 @@ All ShuttleMove procs go here
return TRUE
contents -= oldT
turfs_to_uncontain += oldT
underlying_old_area.contents += oldT
underlying_old_area.contained_turfs += oldT
oldT.transfer_area_lighting(src, underlying_old_area)
//The old turf has now been given back to the area that turf originaly belonged to
@@ -179,7 +181,9 @@ All ShuttleMove procs go here
parallax_movedir = old_dest_area.parallax_movedir
old_dest_area.contents -= newT
old_dest_area.turfs_to_uncontain += newT
contents += newT
contained_turfs += newT
newT.transfer_area_lighting(old_dest_area, src)
return TRUE
+2
View File
@@ -673,7 +673,9 @@
if(!oldT || !istype(oldT.loc, area_type))
continue
var/area/old_area = oldT.loc
old_area.turfs_to_uncontain += oldT
underlying_area.contents += oldT
underlying_area.contained_turfs += oldT
oldT.transfer_area_lighting(old_area, underlying_area)
oldT.empty(FALSE)
+3 -2
View File
@@ -53,8 +53,8 @@
#define TEST_PRE 0
#define TEST_DEFAULT 1
/// This should be one of the last tests to run, because we run it for a little bit over 30 seconds by design and we want to run all of the tests that take a trivial amount of time to complete beforehand.
#define TEST_MONKEY_BUSINESS 10
/// After most test steps, used for tests that run long so shorter issues can be noticed faster
#define TEST_LONGER 10
/// This must be the last test to run due to the inherent nature of the test iterating every single tangible atom in the game and qdeleting all of them (while taking long sleeps to make sure the garbage collector fires properly) taking a large amount of time.
#define TEST_CREATE_AND_DESTROY INFINITY
@@ -82,6 +82,7 @@
#include "achievements.dm"
#include "anchored_mobs.dm"
#include "anonymous_themes.dm"
#include "area_contents.dm"
#include "autowiki.dm"
#include "barsigns.dm"
#include "bespoke_id.dm"
+30
View File
@@ -0,0 +1,30 @@
/// Verifies that an area's perception of their "turfs" is correct, and no other area overlaps with them
/// Quite slow, but needed
/datum/unit_test/area_contents
priority = TEST_LONGER
/datum/unit_test/area_contents/Run()
/// assoc list of turfs -> areas
var/list/turf_to_area = list()
// 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")
var/area/existing = turf_to_area[position]
if(existing == space)
TEST_FAIL("Found a duplicate turf [position.type] inside [space.type]'s turf listing")
else if(existing)
TEST_FAIL("Found a shared turf [position.type] between [space.type] and [existing.type]'s turf listings")
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]")
turf_to_area[position] = space
for(var/turf/position in ALL_TURFS())
if(!turf_to_area[position])
TEST_FAIL("Found a turf [position.type] inside [position.loc.type] that is NOT stored in any area's turf listing")
+1 -1
View File
@@ -8,7 +8,7 @@
* but its also hilarious and fun to watch locally.
*/
/datum/unit_test/monkey_business
priority = TEST_MONKEY_BUSINESS
priority = TEST_LONGER
var/monkey_timer = 30 SECONDS
var/monkey_angry_nth = 5 // every nth monkey will be angry
@@ -56,8 +56,8 @@
var/obj/structure/spacevine/vine = new()
for(var/area/station/maintenance/maint_area in world)
for(var/turf/floor in maint_area)
for(var/area/station/maintenance/maint_area in GLOB.areas)
for(var/turf/floor as anything in maint_area.get_contained_turfs())
if(floor.Enter(vine))
turfs += floor
@@ -204,8 +204,8 @@
var/obj/structure/test_structure = new() // This is apparently the most intuative way to check if a turf is able to support entering.
for(var/area/station/maintenance/maint_area in world)
for(var/turf/floor in maint_area)
for(var/area/station/maintenance/maint_area in GLOB.areas)
for(var/turf/floor as anything in maint_area.get_contained_turfs())
if(!is_station_level(floor.z))
continue
if(floor.Enter(test_structure))
@@ -82,7 +82,7 @@ SUBSYSTEM_DEF(area_spawn)
turf_list = area_turf_info["[mode]"] = list()
// Get highest priority items
for(var/turf/iterating_turf in area)
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)
@@ -30,12 +30,12 @@
var/list/possible_spawn_areas = typecacheof(typesof(/area/station/maintenance, /area/station/security/prison, /area/station/construction))
for(var/area/A in world)
for(var/area/A as anything in GLOB.areas)
if(!is_station_level(A.z))
continue
if(!is_type_in_typecache(A, possible_spawn_areas))
continue
for(var/turf/open/floor in A)
for(var/turf/open/floor in A.get_contained_turfs())
if(!floor.Enter(resintest))
continue
if(locate(/turf/closed) in range(2, floor))
@@ -45,18 +45,17 @@ SUBSYSTEM_DEF(decay)
log_world("SSDecay will not interact with this round.")
return SS_INIT_NO_NEED
for(var/turf/iterating_turf in world)
if(!is_station_level(iterating_turf.z))
continue
if(!(iterating_turf.flags_1 & CAN_BE_DIRTY_1))
continue
possible_turfs += iterating_turf
for(var/area/iterating_area in world)
for(var/area/iterating_area as anything in GLOB.areas)
if(!is_station_level(iterating_area.z))
continue
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
if(!possible_turfs)
CRASH("SSDecay had no possible turfs to use!")
+1
View File
@@ -562,6 +562,7 @@
#include "code\controllers\subsystem\ai_controllers.dm"
#include "code\controllers\subsystem\air.dm"
#include "code\controllers\subsystem\ambience.dm"
#include "code\controllers\subsystem\area_contents.dm"
#include "code\controllers\subsystem\asset_loading.dm"
#include "code\controllers\subsystem\assets.dm"
#include "code\controllers\subsystem\atoms.dm"