mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-08-26 06:22:26 +01:00
Added the z-level manager system from TG (#19532)
Added the z-level manager system from TG, mostly
This commit is contained in:
@@ -58,8 +58,10 @@
|
||||
..()
|
||||
else
|
||||
var/datum/gas_mixture/pipe_air = return_air()
|
||||
var/turf/T = get_turf(loc)
|
||||
var/turf/turf_above = GET_TURF_ABOVE(T)
|
||||
|
||||
if(istype(loc, /turf/space) || (isopenturf(loc) && (istype(GetBelow(loc), /turf/space) || istype(GetAbove(loc), /turf/space))))
|
||||
if(istype(loc, /turf/space) || (isopenturf(loc) && (istype(GET_TURF_BELOW(T), /turf/space) || istype(turf_above, /turf/space))))
|
||||
parent.radiate_heat_to_space(surface, 1)
|
||||
|
||||
else if(istype(loc, /turf/simulated/lava))
|
||||
|
||||
@@ -655,7 +655,7 @@
|
||||
var/obj/structure/lattice/L = locate() in T
|
||||
if(L)
|
||||
return L.name
|
||||
var/turf/leapBelow = GetBelow(T)
|
||||
var/turf/leapBelow = GET_TURF_BELOW(T)
|
||||
if(leapBelow.density)
|
||||
return leapBelow.name
|
||||
else if(T.contains_dense_objects())
|
||||
@@ -718,7 +718,8 @@
|
||||
H.throw_at(T, leapDistance, 1, spin = FALSE)
|
||||
return TRUE
|
||||
else
|
||||
var/turf/simulated/open/TA = GetAbove(src)
|
||||
var/turf/current_turf = get_turf(src)
|
||||
var/turf/simulated/open/TA = GET_TURF_ABOVE(current_turf)
|
||||
if (!istype(TA))
|
||||
to_chat(user, SPAN_WARNING("There is a ceiling above you that stop you from leaping upwards!"))
|
||||
return FALSE
|
||||
|
||||
@@ -136,7 +136,7 @@ var/list/REVERSE_LIGHTING_CORNER_DIAGONAL = list(0, 0, 0, 0, 3, 4, 0, 0, 2, 1)
|
||||
|
||||
#define AVERAGE_BELOW_CORNER(Tt, Ti) \
|
||||
if (TURF_IS_MIMICING(Tt)) { \
|
||||
T = GET_BELOW(Tt); \
|
||||
T = GET_TURF_BELOW(Tt); \
|
||||
if (T && T.corners && TURF_IS_DYNAMICALLY_LIT_UNSAFE(T)) { \
|
||||
C = T.corners[Ti]; \
|
||||
if (C) { \
|
||||
@@ -150,7 +150,7 @@ var/list/REVERSE_LIGHTING_CORNER_DIAGONAL = list(0, 0, 0, 0, 3, 4, 0, 0, 2, 1)
|
||||
|
||||
#define UPDATE_ABOVE_CORNER(Tt, Ti) \
|
||||
if (Tt) { \
|
||||
T = GET_ABOVE(Tt); \
|
||||
T = GET_TURF_ABOVE(Tt); \
|
||||
if (TURF_IS_MIMICING(T) && TURF_IS_DYNAMICALLY_LIT_UNSAFE(T)) { \
|
||||
if (!T.corners) { \
|
||||
T.generate_missing_corners(); \
|
||||
|
||||
@@ -58,8 +58,33 @@
|
||||
|
||||
//Since SSicon_smooth.add_to_queue() manually wakes the subsystem, we have to use enable/disable.
|
||||
SSicon_smooth.can_fire = FALSE
|
||||
for (var/mappath in mappaths)
|
||||
var/datum/map_load_metadata/M = maploader.load_map(file(mappath), x, y, no_changeturf = no_changeturf)
|
||||
var/is_first = TRUE
|
||||
|
||||
for(var/i in 1 to length(mappaths))
|
||||
var/mappath = mappaths[i]
|
||||
|
||||
var/list/trait = ZTRAITS_AWAY
|
||||
|
||||
//Second or subsequent map file
|
||||
if(!is_first)
|
||||
//Last map file in a multi level map, can only go down
|
||||
if(i == length(mappaths))
|
||||
trait += list(ZTRAIT_UP = FALSE, ZTRAIT_DOWN = TRUE)
|
||||
//Intermediate map file, can go up and down
|
||||
else
|
||||
trait += list(ZTRAIT_UP = TRUE, ZTRAIT_DOWN = TRUE)
|
||||
|
||||
//First map file
|
||||
else
|
||||
//Multi-level map
|
||||
if(length(mappaths) >= 2)
|
||||
trait += list(ZTRAIT_UP = TRUE, ZTRAIT_DOWN = FALSE)
|
||||
//Single-level map
|
||||
else
|
||||
trait += list(ZTRAIT_UP = FALSE, ZTRAIT_DOWN = FALSE)
|
||||
|
||||
var/datum/space_level/level = SSmapping.add_new_zlevel(name, trait, contain_turfs = FALSE)
|
||||
var/datum/map_load_metadata/M = maploader.load_map(file(mappath), x, y, level.z_value, no_changeturf = no_changeturf)
|
||||
if (M)
|
||||
bounds = extend_bounds_if_needed(bounds, M.bounds)
|
||||
atoms_to_initialise += M.atoms_to_initialise
|
||||
@@ -67,6 +92,8 @@
|
||||
SSicon_smooth.can_fire = TRUE
|
||||
return FALSE
|
||||
|
||||
is_first = FALSE
|
||||
|
||||
for (var/z_index = bounds[MAP_MINZ]; z_index <= bounds[MAP_MAXZ]; z_index++)
|
||||
if (accessibility_weight)
|
||||
SSatlas.current_map.accessible_z_levels[num2text(z_index)] = accessibility_weight
|
||||
@@ -110,7 +110,7 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new)
|
||||
var/zcrd = text2num(dmmRegex.group[5]) + z_offset - 1
|
||||
|
||||
var/zexpansion = zcrd > world.maxz
|
||||
if(zexpansion)
|
||||
if(zexpansion && !measureOnly) // don't actually expand the world if we're only measuring bounds
|
||||
if(cropMap)
|
||||
continue
|
||||
else
|
||||
@@ -0,0 +1,22 @@
|
||||
/datum/space_level
|
||||
var/name = "NAME MISSING"
|
||||
var/list/neigbours = list()
|
||||
var/list/traits
|
||||
var/z_value = 1 //actual z placement
|
||||
var/linkage = SELFLOOPING
|
||||
var/xi
|
||||
var/yi //imaginary placements on the grid
|
||||
|
||||
/datum/space_level/New(new_z, new_name, list/new_traits = list())
|
||||
z_value = new_z
|
||||
name = new_name
|
||||
traits = new_traits
|
||||
|
||||
if (islist(new_traits))
|
||||
for (var/trait in new_traits)
|
||||
SSmapping.z_trait_levels[trait] += list(new_z)
|
||||
else // in case a single trait is passed in
|
||||
SSmapping.z_trait_levels[new_traits] += list(new_z)
|
||||
|
||||
|
||||
set_linkage(new_traits[ZTRAIT_LINKAGE])
|
||||
@@ -0,0 +1,95 @@
|
||||
/* THIS IS ONLY A PLACEHOLDER AND DOESN'T WORK */
|
||||
|
||||
//Yes, they can only be rectangular.
|
||||
//Yes, I'm sorry.
|
||||
/datum/turf_reservation
|
||||
/// All turfs that we've reserved
|
||||
var/list/reserved_turfs = list()
|
||||
|
||||
/// Turfs around the reservation for cordoning
|
||||
var/list/cordon_turfs = list()
|
||||
|
||||
/// Area of turfs next to the cordon to fill with pre_cordon_area's
|
||||
var/list/pre_cordon_turfs = list()
|
||||
|
||||
/// The width of the reservation
|
||||
var/width = 0
|
||||
|
||||
/// The height of the reservation
|
||||
var/height = 0
|
||||
|
||||
/// The z stack size of the reservation. Note that reservations are ALWAYS reserved from the bottom up
|
||||
var/z_size = 0
|
||||
|
||||
/// List of the bottom left turfs. Indexed by what their z index for this reservation is
|
||||
var/list/bottom_left_turfs = list()
|
||||
|
||||
/// List of the top right turfs. Indexed by what their z index for this reservation is
|
||||
var/list/top_right_turfs = list()
|
||||
|
||||
/// The turf type the reservation is initially made with
|
||||
var/turf_type = /turf/space
|
||||
|
||||
///Distance away from the cordon where we can put a "sort-cordon" and run some extra code (see make_repel). 0 makes nothing happen
|
||||
var/pre_cordon_distance = 0
|
||||
|
||||
/// Calculates the effective bounds information for the given turf. Returns a list of the information, or null if not applicable.
|
||||
/datum/turf_reservation/proc/calculate_turf_bounds_information(turf/target)
|
||||
for(var/z_idx in 1 to z_size)
|
||||
var/turf/bottom_left = bottom_left_turfs[z_idx]
|
||||
var/turf/top_right = top_right_turfs[z_idx]
|
||||
var/bl_x = bottom_left.x
|
||||
var/bl_y = bottom_left.y
|
||||
var/tr_x = top_right.x
|
||||
var/tr_y = top_right.y
|
||||
|
||||
if(target.x < bl_x)
|
||||
continue
|
||||
|
||||
if(target.y < bl_y)
|
||||
continue
|
||||
|
||||
if(target.x > tr_x)
|
||||
continue
|
||||
|
||||
if(target.y > tr_y)
|
||||
continue
|
||||
|
||||
var/list/return_information = list()
|
||||
return_information["z_idx"] = z_idx
|
||||
return_information["offset_x"] = target.x - bl_x
|
||||
return_information["offset_y"] = target.y - bl_y
|
||||
return return_information
|
||||
return null
|
||||
|
||||
/// Gets the turf below the given target. Returns null if there is no turf below the target
|
||||
/datum/turf_reservation/proc/get_turf_below(turf/target)
|
||||
var/list/bounds_info = calculate_turf_bounds_information(target)
|
||||
if(isnull(bounds_info))
|
||||
return null
|
||||
|
||||
var/z_idx = bounds_info["z_idx"]
|
||||
// check what z level, if its the max, then there is no turf below
|
||||
if(z_idx == z_size)
|
||||
return null
|
||||
|
||||
var/offset_x = bounds_info["offset_x"]
|
||||
var/offset_y = bounds_info["offset_y"]
|
||||
var/turf/bottom_left = bottom_left_turfs[z_idx + 1]
|
||||
return locate(bottom_left.x + offset_x, bottom_left.y + offset_y, bottom_left.z)
|
||||
|
||||
/// Gets the turf above the given target. Returns null if there is no turf above the target
|
||||
/datum/turf_reservation/proc/get_turf_above(turf/target)
|
||||
var/list/bounds_info = calculate_turf_bounds_information(target)
|
||||
if(isnull(bounds_info))
|
||||
return null
|
||||
|
||||
var/z_idx = bounds_info["z_idx"]
|
||||
// check what z level, if its the min, then there is no turf above
|
||||
if(z_idx == 1)
|
||||
return null
|
||||
|
||||
var/offset_x = bounds_info["offset_x"]
|
||||
var/offset_y = bounds_info["offset_y"]
|
||||
var/turf/bottom_left = bottom_left_turfs[z_idx - 1]
|
||||
return locate(bottom_left.x + offset_x, bottom_left.y + offset_y, bottom_left.z)
|
||||
@@ -0,0 +1,6 @@
|
||||
/datum/space_level/proc/set_linkage(new_linkage)
|
||||
linkage = new_linkage
|
||||
if(linkage == SELFLOOPING)
|
||||
neigbours = list(TEXT_NORTH,TEXT_SOUTH,TEXT_EAST,TEXT_WEST)
|
||||
for(var/A in neigbours)
|
||||
neigbours[A] = src
|
||||
@@ -0,0 +1,16 @@
|
||||
/// Look up levels[z].traits[trait]
|
||||
/datum/controller/subsystem/mapping/proc/level_trait(z, trait)
|
||||
if (!isnum(z) || z < 1)
|
||||
return null
|
||||
if (z_list)
|
||||
if (z > z_list.len)
|
||||
stack_trace("Unmanaged z-level [z]! maxz = [world.maxz], z_list.len = [z_list.len]")
|
||||
return list()
|
||||
var/datum/space_level/S = z_list[z]
|
||||
return S.traits[trait]
|
||||
else
|
||||
var/list/default = DEFAULT_MAP_TRAITS
|
||||
if (z > default.len)
|
||||
stack_trace("Unmanaged z-level [z]! maxz = [world.maxz], default.len = [default.len]")
|
||||
return list()
|
||||
return default[z][DL_TRAITS][trait]
|
||||
@@ -0,0 +1,21 @@
|
||||
/// Generates a real, honest to god new z level. Will create the actual space, and also generate a datum that holds info about the new plot of land
|
||||
/// Accepts the name, traits list, datum type, and if we should manage the turfs we create
|
||||
/datum/controller/subsystem/mapping/proc/add_new_zlevel(name, traits = list(), z_type = /datum/space_level, contain_turfs = TRUE)
|
||||
UNTIL(!adding_new_zlevel)
|
||||
adding_new_zlevel = TRUE
|
||||
var/new_z = z_list.len + 1
|
||||
if (world.maxz < new_z)
|
||||
world.incrementMaxZ()
|
||||
CHECK_TICK
|
||||
// TODO: sleep here if the Z level needs to be cleared
|
||||
var/datum/space_level/S = new z_type(new_z, name, traits)
|
||||
manage_z_level(S, filled_with_space = TRUE, contain_turfs = contain_turfs)
|
||||
generate_linkages_for_z_level(new_z)
|
||||
adding_new_zlevel = FALSE
|
||||
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_NEW_Z, S)
|
||||
return S
|
||||
|
||||
/datum/controller/subsystem/mapping/proc/get_level(z)
|
||||
if (z_list && z >= 1 && z <= z_list.len)
|
||||
return z_list[z]
|
||||
CRASH("Unmanaged z-level [z]! maxz = [world.maxz], z_list.len = [z_list ? z_list.len : "null"]")
|
||||
@@ -109,7 +109,7 @@
|
||||
attached_satchel.insert_into_storage(ore)
|
||||
else if(istype(get_turf(src), /turf/simulated/floor))
|
||||
var/turf/simulated/floor/T = get_turf(src)
|
||||
var/turf/below_turf = GetBelow(T)
|
||||
var/turf/below_turf = GET_TURF_BELOW(T)
|
||||
if(below_turf && !istype(below_turf.loc, /area/mine) && !istype(below_turf.loc, /area/exoplanet) && !istype(below_turf.loc, /area/template_noop))
|
||||
system_error("Potential station breach below.")
|
||||
return
|
||||
|
||||
@@ -1262,7 +1262,8 @@ var/list/total_extraction_beacons = list()
|
||||
|
||||
return TRUE
|
||||
if("ladder")
|
||||
var/turf/above = GET_ABOVE(src)
|
||||
var/turf/T = get_turf(src)
|
||||
var/turf/above = GET_TURF_ABOVE(T)
|
||||
if(!above)
|
||||
to_chat(user, SPAN_WARNING("There is nothing above you to make a ladder towards."))
|
||||
return FALSE
|
||||
@@ -1278,7 +1279,8 @@ var/list/total_extraction_beacons = list()
|
||||
return TRUE
|
||||
return FALSE
|
||||
if("ladder")
|
||||
var/turf/above = GET_ABOVE(src)
|
||||
var/turf/T = get_turf(src)
|
||||
var/turf/above = GET_TURF_ABOVE(T)
|
||||
if(!above)
|
||||
to_chat(user, SPAN_WARNING("There is nothing above you to make a ladder towards."))
|
||||
return FALSE
|
||||
@@ -1323,7 +1325,8 @@ var/list/total_extraction_beacons = list()
|
||||
return TRUE
|
||||
|
||||
if("ladder")
|
||||
var/turf/above = GET_ABOVE(src)
|
||||
var/turf/T = get_turf(src)
|
||||
var/turf/above = GET_TURF_ABOVE(T)
|
||||
if(!above)
|
||||
to_chat(user, SPAN_WARNING("There is nothing above you to make a ladder towards."))
|
||||
return FALSE
|
||||
|
||||
@@ -600,7 +600,8 @@ var/list/mineral_can_smooth_with = list(
|
||||
|
||||
if(ishuman(user) && user.a_intent == I_GRAB)
|
||||
var/mob/living/carbon/human/H = user
|
||||
var/turf/destination = GetAbove(H)
|
||||
var/turf/T = get_turf(H)
|
||||
var/turf/destination = GET_TURF_ABOVE(T)
|
||||
if(destination)
|
||||
var/turf/start = get_turf(H)
|
||||
if(start.CanZPass(H, UP))
|
||||
@@ -816,7 +817,7 @@ var/list/asteroid_floor_smooth = list(
|
||||
if(digging)
|
||||
return
|
||||
if(dug)
|
||||
if(!GetBelow(src))
|
||||
if(!GET_TURF_BELOW(src))
|
||||
return
|
||||
to_chat(user, SPAN_NOTICE("You start digging deeper."))
|
||||
playsound(get_turf(user), 'sound/effects/stonedoor_openclose.ogg', 50, TRUE)
|
||||
@@ -960,7 +961,7 @@ var/list/asteroid_floor_smooth = list(
|
||||
dug += 1
|
||||
AddOverlays("asteroid_dug", TRUE)
|
||||
else
|
||||
var/turf/below = GetBelow(src)
|
||||
var/turf/below = GET_TURF_BELOW(src)
|
||||
if(below)
|
||||
var/area/below_area = get_area(below) // Let's just assume that the turf is not in nullspace.
|
||||
if(below_area.station_area)
|
||||
|
||||
@@ -2264,7 +2264,8 @@
|
||||
reset_view(null)
|
||||
QDEL_NULL(z_eye)
|
||||
return
|
||||
var/turf/above = GetAbove(src)
|
||||
var/turf/T = get_turf(src)
|
||||
var/turf/above = GET_TURF_ABOVE(T)
|
||||
if(TURF_IS_MIMICING(above))
|
||||
z_eye = new /atom/movable/z_observer/z_up(src, src)
|
||||
visible_message(SPAN_NOTICE("[src] looks up."), SPAN_NOTICE("You look up."))
|
||||
@@ -2285,14 +2286,14 @@
|
||||
QDEL_NULL(z_eye)
|
||||
return
|
||||
var/turf/T = get_turf(src)
|
||||
if(TURF_IS_MIMICING(T) && HasBelow(T.z))
|
||||
if(TURF_IS_MIMICING(T) && GET_TURF_BELOW(T))
|
||||
z_eye = new /atom/movable/z_observer/z_down(src, src)
|
||||
visible_message(SPAN_NOTICE("[src] looks below."), SPAN_NOTICE("You look below."))
|
||||
reset_view(z_eye)
|
||||
return
|
||||
else
|
||||
T = get_step(T, dir)
|
||||
if(TURF_IS_MIMICING(T) && HasBelow(T.z))
|
||||
if(TURF_IS_MIMICING(T) && GET_TURF_BELOW(T))
|
||||
z_eye = new /atom/movable/z_observer/z_down(src, src, TRUE)
|
||||
visible_message(SPAN_NOTICE("[src] leans over to look below."), SPAN_NOTICE("You lean over to look below."))
|
||||
reset_view(z_eye)
|
||||
|
||||
@@ -395,7 +395,8 @@
|
||||
else
|
||||
visible_message(SPAN_DANGER("[H] pushes [src] forward!"), SPAN_DANGER("[H] pushes you forward!"))
|
||||
apply_effect(5, WEAKEN)
|
||||
forceMove(GetAbove(z_eye)) //We use GetAbove so people can't cheese it by turning their sprite.
|
||||
var/turf/current_turf = get_turf(z_eye)
|
||||
forceMove(GET_TURF_ABOVE(current_turf)) //We use GET_TURF_ABOVE so people can't cheese it by turning their sprite.
|
||||
return
|
||||
|
||||
if(randn <= 25)
|
||||
|
||||
@@ -150,7 +150,7 @@
|
||||
footsound = T.footstep_sound
|
||||
|
||||
if (client)
|
||||
var/turf/B = GetAbove(T)
|
||||
var/turf/B = GET_TURF_ABOVE(T)
|
||||
if(up_hint)
|
||||
up_hint.icon_state = "uphint[(B ? !!B.is_hole : 0)]"
|
||||
|
||||
|
||||
@@ -27,11 +27,11 @@
|
||||
var/turf/T = get_turf(target)
|
||||
var/damage_mod = 1
|
||||
var/from_above = FALSE
|
||||
if(H.can_fall(GET_BELOW(T)))
|
||||
if(H.can_fall(GET_TURF_BELOW(T)))
|
||||
from_above = TRUE
|
||||
if(isopenspace(T))
|
||||
while(isopenspace(T))
|
||||
T = GET_BELOW(T)
|
||||
T = GET_TURF_BELOW(T)
|
||||
damage_mod += 1
|
||||
if(isturf(T))
|
||||
T.visible_message(SPAN_DANGER("[H] lands on \the [T] with a quake!"))
|
||||
|
||||
@@ -66,7 +66,8 @@
|
||||
to_chat(cleaned_human, SPAN_WARNING("\The [src] runs its bottom mounted bristles all over you!"))
|
||||
|
||||
if(client)
|
||||
var/turf/B = GetAbove(get_turf(src))
|
||||
var/turf/T = get_turf(src)
|
||||
var/turf/B = GET_TURF_ABOVE(T)
|
||||
if(up_hint)
|
||||
up_hint.icon_state = "uphint[(B ? !!B.is_hole : 0)]"
|
||||
|
||||
|
||||
@@ -1492,12 +1492,12 @@
|
||||
if(!T.is_outside())
|
||||
|
||||
// For non-multiz we'll give everyone some nice ambience.
|
||||
if(!HasAbove(T.z))
|
||||
if(!GET_TURF_ABOVE(T))
|
||||
return WEATHER_ROOFED
|
||||
|
||||
// For multi-z, check the actual weather on the turf above.
|
||||
// TODO: maybe make this a property of the z-level marker.
|
||||
var/turf/above = GetAbove(T)
|
||||
var/turf/above = GET_TURF_ABOVE(T)
|
||||
if(above.weather)
|
||||
return WEATHER_ROOFED
|
||||
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
// If you add a more comprehensive system, just untick this file.
|
||||
// Because this shit before was, for some reason, a bitfield.
|
||||
GLOBAL_LIST_EMPTY(z_levels)
|
||||
var/list/list/connected_z_cache = list()
|
||||
|
||||
// If the height is more than 1, we mark all contained levels as connected.
|
||||
@@ -10,43 +7,16 @@ var/list/list/connected_z_cache = list()
|
||||
return
|
||||
if(_height)
|
||||
height = _height
|
||||
for(var/i = (loc.z - height + 1) to (loc.z-1))
|
||||
if (GLOB.z_levels.len <i)
|
||||
GLOB.z_levels.len = i
|
||||
GLOB.z_levels[i] = TRUE
|
||||
|
||||
/obj/effect/landmark/map_data/Initialize()
|
||||
..()
|
||||
return INITIALIZE_HINT_QDEL
|
||||
|
||||
/proc/HasAbove(var/z)
|
||||
if(z >= world.maxz || z < 1 || z > GLOB.z_levels.len)
|
||||
return 0
|
||||
return GLOB.z_levels[z]
|
||||
|
||||
/proc/HasBelow(var/z)
|
||||
if(z > world.maxz || z < 2 || (z-1) > GLOB.z_levels.len)
|
||||
return 0
|
||||
return GLOB.z_levels[z-1]
|
||||
|
||||
// Thankfully, no bitwise magic is needed here.
|
||||
/proc/GetAbove(var/atom/atom)
|
||||
var/turf/turf = get_turf(atom)
|
||||
if(!turf)
|
||||
return null
|
||||
return HasAbove(turf.z) ? get_step(turf, UP) : null
|
||||
|
||||
/proc/GetBelow(var/atom/atom)
|
||||
var/turf/turf = get_turf(atom)
|
||||
if(!turf)
|
||||
return null
|
||||
return HasBelow(turf.z) ? get_step(turf, DOWN) : null
|
||||
|
||||
/proc/GetConnectedZlevels(z)
|
||||
. = list(z)
|
||||
for(var/level = z, HasBelow(level), level--)
|
||||
for(var/level = z, SSmapping.multiz_levels[level][Z_LEVEL_DOWN], level--)
|
||||
. |= level-1
|
||||
for(var/level = z, HasAbove(level), level++)
|
||||
for(var/level = z, SSmapping.multiz_levels[level][Z_LEVEL_UP], level++)
|
||||
. |= level+1
|
||||
|
||||
/proc/AreConnectedZLevels(var/zA, var/zB)
|
||||
@@ -76,10 +46,11 @@ var/list/list/connected_z_cache = list()
|
||||
CRASH("Expected atom.")
|
||||
if (!ref.z)
|
||||
ref = get_turf(ref)
|
||||
var/turf/T = get_turf(ref)
|
||||
switch (dir)
|
||||
if (UP)
|
||||
. = GET_ABOVE(ref)
|
||||
. = GET_TURF_ABOVE(T)
|
||||
if (DOWN)
|
||||
. = GET_BELOW(ref)
|
||||
. = GET_TURF_BELOW(T)
|
||||
else
|
||||
. = get_step(ref, dir)
|
||||
|
||||
@@ -3,8 +3,3 @@
|
||||
return 0
|
||||
/proc/HasBelow(var/z)
|
||||
return 0
|
||||
// These give either the turf or null.
|
||||
/proc/GetAbove(var/turf/turf)
|
||||
return null
|
||||
/proc/GetBelow(var/turf/turf)
|
||||
return null
|
||||
|
||||
@@ -229,7 +229,8 @@
|
||||
collapse_kit()
|
||||
|
||||
/obj/structure/hoist/proc/can_move_dir(direction)
|
||||
var/turf/dest = direction == UP ? GetAbove(source_hook) : GetBelow(source_hook)
|
||||
var/turf/T = get_turf(source_hook)
|
||||
var/turf/dest = direction == UP ? GET_TURF_ABOVE(T) : GET_TURF_BELOW(T)
|
||||
switch(direction)
|
||||
if (UP)
|
||||
if (!isopenturf(dest)) // can't move into a solid tile
|
||||
@@ -247,7 +248,8 @@
|
||||
/obj/structure/hoist/proc/move_dir(direction)
|
||||
if (!can_move_dir(direction))
|
||||
return FALSE
|
||||
var/turf/move_dest = direction == UP ? GetAbove(source_hook) : GetBelow(source_hook)
|
||||
var/turf/T = get_turf(source_hook)
|
||||
var/turf/move_dest = direction == UP ? GET_TURF_ABOVE(T) : GET_TURF_BELOW(T)
|
||||
source_hook.forceMove(move_dest)
|
||||
if (hoistee)
|
||||
hoistee.hoist_act(move_dest)
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
/obj/item/ladder_mobile/proc/place_ladder(atom/A, mob/user)
|
||||
|
||||
if (isopenturf(A)) //Place into open space
|
||||
var/turf/below_loc = GetBelow(A)
|
||||
var/turf/T = get_turf(A)
|
||||
var/turf/below_loc = GET_TURF_BELOW(T)
|
||||
if (!below_loc || (istype(/turf/space, below_loc)))
|
||||
to_chat(user, SPAN_NOTICE("Why would you do that?! There is only infinite space there..."))
|
||||
return
|
||||
@@ -32,7 +33,8 @@
|
||||
qdel(src)
|
||||
|
||||
else if (istype(A, /turf/simulated/floor) || istype(A, /turf/unsimulated/floor)) //Place onto Floor
|
||||
var/turf/upper_loc = GetAbove(A)
|
||||
var/turf/T = get_turf(A)
|
||||
var/turf/upper_loc = GET_TURF_ABOVE(T)
|
||||
if (!upper_loc || !isopenturf(upper_loc))
|
||||
to_chat(user, SPAN_NOTICE("There is something above. You can't deploy!"))
|
||||
return
|
||||
|
||||
@@ -40,7 +40,8 @@
|
||||
to_chat(src, SPAN_WARNING("You lack means of travel in that direction."))
|
||||
return FALSE
|
||||
|
||||
var/turf/destination = (direction == UP) ? GetAbove(src) : GetBelow(src)
|
||||
var/turf/T = get_turf(src)
|
||||
var/turf/destination = (direction == UP) ? GET_TURF_ABOVE(T) : GET_TURF_BELOW(T)
|
||||
|
||||
if(!destination)
|
||||
to_chat(src, SPAN_NOTICE("There is nothing of interest in this direction."))
|
||||
@@ -104,14 +105,16 @@
|
||||
return ..()
|
||||
|
||||
/mob/abstract/eye/zMove(direction)
|
||||
var/turf/destination = (direction == UP) ? GetAbove(src) : GetBelow(src)
|
||||
var/turf/T = get_turf(src)
|
||||
var/turf/destination = (direction == UP) ? GET_TURF_ABOVE(T) : GET_TURF_BELOW(T)
|
||||
if(destination)
|
||||
setLoc(destination)
|
||||
else
|
||||
to_chat(owner, SPAN_NOTICE("There is nothing of interest in this direction."))
|
||||
|
||||
/mob/abstract/observer/zMove(direction)
|
||||
var/turf/destination = (direction == UP) ? GetAbove(src) : GetBelow(src)
|
||||
var/turf/T = get_turf(src)
|
||||
var/turf/destination = (direction == UP) ? GET_TURF_ABOVE(T) : GET_TURF_BELOW(T)
|
||||
if(destination)
|
||||
forceMove(destination)
|
||||
else
|
||||
@@ -151,9 +154,9 @@
|
||||
/mob/living/carbon/human/proc/climb(var/direction, var/turf/source, var/climb_bonus)
|
||||
var/turf/destination
|
||||
if(direction == UP)
|
||||
destination = GetAbove(source)
|
||||
destination = GET_TURF_ABOVE(source)
|
||||
else
|
||||
destination = GetBelow(source)
|
||||
destination = GET_TURF_BELOW(source)
|
||||
|
||||
if(!destination)
|
||||
return
|
||||
|
||||
@@ -167,7 +167,8 @@
|
||||
node1 = target
|
||||
break
|
||||
|
||||
var/turf/above = GetAbove(src)
|
||||
var/turf/current_turf = get_turf(src)
|
||||
var/turf/above = GET_TURF_ABOVE(current_turf)
|
||||
if(above)
|
||||
for(var/obj/machinery/atmospherics/target in above)
|
||||
if(target.initialize_directions && istype(target, /obj/machinery/atmospherics/pipe/zpipe/down))
|
||||
@@ -210,7 +211,8 @@
|
||||
node1 = target
|
||||
break
|
||||
|
||||
var/turf/below = GetBelow(src)
|
||||
var/turf/T = get_turf(src)
|
||||
var/turf/below = GET_TURF_BELOW(T)
|
||||
if(below)
|
||||
for(var/obj/machinery/atmospherics/target in below)
|
||||
if(target.initialize_directions && istype(target, /obj/machinery/atmospherics/pipe/zpipe/up))
|
||||
@@ -219,7 +221,6 @@
|
||||
break
|
||||
|
||||
|
||||
var/turf/T = src.loc // hide if turf is not intact
|
||||
hide(!T.is_plating())
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
@@ -34,7 +34,8 @@
|
||||
. = ..()
|
||||
// the upper will connect to the lower
|
||||
if(allowed_directions & DOWN) //we only want to do the top one, as it will initialize the ones before it.
|
||||
for(var/obj/structure/ladder/L in GetBelow(src))
|
||||
var/turf/T = get_turf(src)
|
||||
for(var/obj/structure/ladder/L in GET_TURF_BELOW(T))
|
||||
if(L.allowed_directions & UP)
|
||||
target_down = L
|
||||
L.target_up = src
|
||||
@@ -237,7 +238,7 @@
|
||||
/obj/structure/stairs/Initialize()
|
||||
. = ..()
|
||||
for(var/turf/turf in locs)
|
||||
var/turf/simulated/open/above = GetAbove(turf)
|
||||
var/turf/simulated/open/above = GET_TURF_ABOVE(turf)
|
||||
if(!above)
|
||||
log_asset("Stair created without z-level above: ([loc.x], [loc.y], [loc.z])")
|
||||
return INITIALIZE_HINT_QDEL
|
||||
@@ -264,7 +265,8 @@
|
||||
var/atom/movable/AM = bumped_atom
|
||||
|
||||
// This is hackish but whatever.
|
||||
var/turf/target = get_step(GetAbove(AM), dir)
|
||||
var/turf/T = get_turf(AM)
|
||||
var/turf/target = get_step(GET_TURF_ABOVE(T), dir)
|
||||
if(!target)
|
||||
return
|
||||
if(target.z > (z + 1)) //Prevents wheelchair fuckery. Basically, you teleport twice because both the wheelchair + your mob collide with the stairs.
|
||||
|
||||
@@ -181,7 +181,8 @@
|
||||
* Updates the turf with open turf's variables and basically resets it properly.
|
||||
*/
|
||||
/turf/simulated/open/proc/update(mapload = FALSE)
|
||||
below = GetBelow(src)
|
||||
var/turf/T = get_turf(src)
|
||||
below = GET_TURF_BELOW(T)
|
||||
|
||||
// Edge case for when an open turf is above space on the lowest level.
|
||||
if (below)
|
||||
@@ -211,7 +212,8 @@
|
||||
. = ..()
|
||||
if(distance <= 2)
|
||||
var/depth = 1
|
||||
for(var/T = GetBelow(src); isopenspace(T); T = GetBelow(T))
|
||||
var/turf/current_turf = get_turf(src)
|
||||
for(var/turf/T = GET_TURF_BELOW(current_turf); isopenspace(T); T = GET_TURF_BELOW(T))
|
||||
depth += 1
|
||||
. += "It is about [depth] level\s deep."
|
||||
|
||||
@@ -259,7 +261,8 @@
|
||||
|
||||
if(ishuman(user) && user.a_intent == I_GRAB)
|
||||
var/mob/living/carbon/human/H = user
|
||||
var/turf/climbing_wall = GetBelow(H)
|
||||
var/turf/T = get_turf(H)
|
||||
var/turf/climbing_wall = GET_TURF_BELOW(T)
|
||||
var/climb_bonus = 0
|
||||
if(istype(climbing_wall, /turf/simulated/mineral))
|
||||
climb_bonus = 20
|
||||
@@ -276,7 +279,7 @@
|
||||
|
||||
//Returns the roof type of the turf below
|
||||
/turf/simulated/open/get_roof_type()
|
||||
var/turf/t = GetBelow(src)
|
||||
var/turf/t = GET_TURF_BELOW(src)
|
||||
if(!t)
|
||||
return null
|
||||
return t.roof_type
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
return
|
||||
|
||||
/turf/proc/is_above_space()
|
||||
var/turf/T = GetBelow(src)
|
||||
var/turf/T = GET_TURF_BELOW(src)
|
||||
while (T && (T.z_flags & ZM_MIMIC_BELOW))
|
||||
T = GetBelow(T)
|
||||
T = GET_TURF_BELOW(T)
|
||||
return isspaceturf(T)
|
||||
|
||||
/turf/update_icon()
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
CRASH("Attempt to enable Z-mimic on already-enabled turf!")
|
||||
shadower = new(src)
|
||||
SSzcopy.openspace_turfs += 1
|
||||
var/turf/under = GetBelow(src)
|
||||
var/turf/under = GET_TURF_BELOW(src)
|
||||
if (under)
|
||||
below = under
|
||||
below.above = src
|
||||
|
||||
@@ -149,9 +149,8 @@
|
||||
planet_name = generate_planet_name()
|
||||
name = "[planet_name], \a [name]"
|
||||
|
||||
world.maxz++
|
||||
forceMove(locate(1,1,world.maxz))
|
||||
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_NEW_Z, world.maxz)
|
||||
var/datum/space_level/exoplanet_level = SSmapping.add_new_zlevel("Exoplanet [name]", ZTRAITS_AWAY, contain_turfs = FALSE)
|
||||
forceMove(locate(1, 1, exoplanet_level.z_value))
|
||||
|
||||
pre_ruin_preparation()
|
||||
if(LAZYLEN(possible_themes))
|
||||
|
||||
@@ -283,13 +283,13 @@ var/global/area/overmap/map_overmap
|
||||
magnet_survey_result = ""
|
||||
|
||||
/proc/build_overmap()
|
||||
set waitfor = FALSE
|
||||
if(!SSatlas.current_map.use_overmap)
|
||||
return 1
|
||||
|
||||
log_module_sectors("Building overmap...")
|
||||
world.maxz++
|
||||
SSatlas.current_map.overmap_z = world.maxz
|
||||
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_NEW_Z, world.maxz)
|
||||
var/datum/space_level/overmap_spacelevel = SSmapping.add_new_zlevel("Overmap", ZTRAITS_OVERMAP, contain_turfs = FALSE)
|
||||
SSatlas.current_map.overmap_z = overmap_spacelevel.z_value
|
||||
|
||||
log_module_sectors("Putting overmap on [SSatlas.current_map.overmap_z]")
|
||||
var/area/overmap/A = new
|
||||
|
||||
@@ -39,10 +39,9 @@
|
||||
/obj/effect/overmap/visitable/ship/landable/find_z_levels()
|
||||
if(!use_mapped_z_levels)
|
||||
for(var/i = 0 to multiz)
|
||||
world.maxz++
|
||||
map_z += world.maxz
|
||||
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_NEW_Z, world.maxz)
|
||||
var/turf/center_loc = locate(round(world.maxx/2), round(world.maxy/2), world.maxz)
|
||||
var/datum/space_level/S = SSmapping.add_new_zlevel("Landable Landmark [i] for [shuttle]", list(ZTRAIT_RESERVED = TRUE), contain_turfs = FALSE)
|
||||
map_z += S.z_value
|
||||
var/turf/center_loc = locate(round(world.maxx/2), round(world.maxy/2), map_z[length(map_z)])
|
||||
landmark = new (center_loc, shuttle)
|
||||
add_landmark(landmark, shuttle)
|
||||
var/visitor_dir = fore_dir
|
||||
@@ -53,7 +52,7 @@
|
||||
visitor_dir = turn(visitor_dir, 90)
|
||||
|
||||
if(multiz)
|
||||
new /obj/effect/landmark/map_data(locate(1, 1, world.maxz), (multiz + 1))
|
||||
new /obj/effect/landmark/map_data(locate(1, 1, map_z[length(map_z)]), (multiz + 1))
|
||||
else
|
||||
..()
|
||||
|
||||
|
||||
@@ -180,7 +180,7 @@ By design, d1 is the smallest direction and d2 is the highest
|
||||
playsound(src.loc, 'sound/items/Wirecutter.ogg', 50, 1)
|
||||
|
||||
if(d1 == 11 || d2 == 11)
|
||||
var/turf/turf = GetBelow(src)
|
||||
var/turf/turf = GET_TURF_BELOW(T)
|
||||
if(turf)
|
||||
for(var/obj/structure/cable/c in turf)
|
||||
if(c.d1 == 12 || c.d2 == 12)
|
||||
@@ -382,12 +382,14 @@ By design, d1 is the smallest direction and d2 is the highest
|
||||
|
||||
// Handle up/down cables
|
||||
if(d1 == 11 || d2 == 11)
|
||||
T = GetBelow(src)
|
||||
var/turf/current_turf = get_turf(src)
|
||||
T = GET_TURF_BELOW(current_turf)
|
||||
if(T)
|
||||
. += power_list(T, src, 12, powernetless_only)
|
||||
|
||||
if(d1 == 12 || d2 == 12)
|
||||
T = GetAbove(src)
|
||||
var/turf/current_turf = get_turf(src)
|
||||
T = GET_TURF_ABOVE(current_turf)
|
||||
if(T)
|
||||
. += power_list(T, src, 11, powernetless_only)
|
||||
|
||||
@@ -792,7 +794,7 @@ By design, d1 is the smallest direction and d2 is the highest
|
||||
return
|
||||
|
||||
var/obj/structure/cable/C = new(F)
|
||||
var/obj/structure/cable/D = new(GetBelow(F))
|
||||
var/obj/structure/cable/D = new(GET_TURF_BELOW(F))
|
||||
|
||||
C.cableColor(color)
|
||||
|
||||
|
||||
@@ -108,12 +108,12 @@
|
||||
if(O.invisibility == 101)
|
||||
O.singularity_act(src, current_size)
|
||||
if(go_up && current_size >= STAGE_FIVE)
|
||||
if(HasAbove(src.z))
|
||||
var/turf/A = GetAbove(src)
|
||||
if(GET_TURF_ABOVE(src))
|
||||
var/turf/A = GET_TURF_ABOVE(src)
|
||||
A.singularity_act(S, current_size, 0, 1)
|
||||
if(go_down && current_size >= STAGE_FIVE)
|
||||
if(HasBelow(src.z))
|
||||
var/turf/B = GetBelow(src)
|
||||
if(GET_TURF_BELOW(src))
|
||||
var/turf/B = GET_TURF_BELOW(src)
|
||||
B.singularity_act(S, current_size, 1, 0)
|
||||
if(istype(src,/turf/simulated/mineral))
|
||||
var/turf/simulated/mineral/M = src
|
||||
|
||||
@@ -507,7 +507,8 @@
|
||||
return FALSE
|
||||
|
||||
/obj/singularity/proc/zMove(direction)
|
||||
var/turf/destination = (direction == UP) ? GetAbove(src) : GetBelow(src)
|
||||
var/turf/T = get_turf(src)
|
||||
var/turf/destination = (direction == UP) ? GET_TURF_ABOVE(T) : GET_TURF_BELOW(T)
|
||||
if(destination)
|
||||
forceMove(destination)
|
||||
|
||||
|
||||
@@ -106,10 +106,12 @@
|
||||
var/turf/T
|
||||
switch(move_dir)
|
||||
if(UP)
|
||||
T = GetAbove(src)
|
||||
var/turf/current_turf = get_turf(src)
|
||||
T = GET_TURF_ABOVE(current_turf)
|
||||
z_move = 1
|
||||
if(DOWN)
|
||||
T = GetBelow(src)
|
||||
var/turf/current_turf = get_turf(src)
|
||||
T = GET_TURF_BELOW(current_turf)
|
||||
z_move = -1
|
||||
else
|
||||
T = get_step(src, move_dir)
|
||||
|
||||
@@ -129,7 +129,7 @@
|
||||
if(EMPTY_CHAR)
|
||||
new_path = mineral_rich
|
||||
if(FLOOR_CHAR)
|
||||
var/turf/below = GET_BELOW(T)
|
||||
var/turf/below = GET_TURF_BELOW(T)
|
||||
if(below)
|
||||
var/area/below_area = below.loc // Let's just assume that the turf is not in nullspace.
|
||||
if(below_area.station_area)
|
||||
|
||||
@@ -1084,7 +1084,8 @@
|
||||
var/obj/structure/disposalpipe/P
|
||||
|
||||
if(nextdir == 12)
|
||||
T = GetAbove(src)
|
||||
var/turf/current_turf = get_turf(src)
|
||||
T = GET_TURF_ABOVE(current_turf)
|
||||
if(!T)
|
||||
H.forceMove(loc)
|
||||
return
|
||||
@@ -1133,7 +1134,8 @@
|
||||
var/obj/structure/disposalpipe/P
|
||||
|
||||
if(nextdir == 11)
|
||||
T = GetBelow(src)
|
||||
var/turf/current_turf = get_turf(src)
|
||||
T = GET_TURF_BELOW(current_turf)
|
||||
if(!T)
|
||||
H.forceMove(src.loc)
|
||||
return
|
||||
|
||||
@@ -287,7 +287,7 @@
|
||||
|
||||
/obj/machinery/shield_gen/proc/getzabove(var/turf/location)
|
||||
var/connected = list()
|
||||
var/turf/above = GetAbove(location)
|
||||
var/turf/above = GET_TURF_ABOVE(location)
|
||||
|
||||
if(above)
|
||||
connected += above
|
||||
@@ -299,7 +299,7 @@
|
||||
|
||||
/obj/machinery/shield_gen/proc/getzbelow(var/turf/location)
|
||||
var/connected = list()
|
||||
var/turf/below = GetBelow(location)
|
||||
var/turf/below = GET_TURF_BELOW(location)
|
||||
|
||||
if(below)
|
||||
connected += below
|
||||
|
||||
@@ -206,9 +206,10 @@
|
||||
var/list/powernets = list()
|
||||
for(var/area/A in shuttle_area)
|
||||
// if there was a zlevel above our origin, erase our ceiling now we're leaving
|
||||
if(HasAbove(current_location.z))
|
||||
var/turf/T = get_turf(current_location)
|
||||
if(GET_TURF_ABOVE(T))
|
||||
for(var/turf/TO in A.contents)
|
||||
var/turf/TA = GetAbove(TO)
|
||||
var/turf/TA = GET_TURF_ABOVE(TO)
|
||||
if(istype(TA, ceiling_type))
|
||||
TA.ChangeTurf(get_base_turf_by_area(TA), 1, 1)
|
||||
if(knockdown)
|
||||
@@ -236,12 +237,13 @@
|
||||
current_location = destination
|
||||
|
||||
// if there's a zlevel above our destination, paint in a ceiling on it so we retain our air
|
||||
if(HasAbove(current_location.z))
|
||||
var/turf/T = get_turf(current_location)
|
||||
if(GET_TURF_ABOVE(T))
|
||||
for(var/area/A in shuttle_area)
|
||||
for(var/turf/TD in A.contents)
|
||||
TD.update_above()
|
||||
TD.update_icon()
|
||||
var/turf/TA = GetAbove(TD)
|
||||
var/turf/TA = GET_TURF_ABOVE(TD)
|
||||
if(istype(TA, get_base_turf_by_area(TA)) || (istype(TA) && TA.is_open()))
|
||||
if(get_area(TA) in shuttle_area)
|
||||
continue
|
||||
|
||||
@@ -98,7 +98,7 @@
|
||||
AM.crush_act()
|
||||
else
|
||||
for(var/turf/simulated/wall/W in origin)
|
||||
var/turf/T = GET_ABOVE(W)
|
||||
var/turf/T = GET_TURF_ABOVE(W)
|
||||
for(var/atom/movable/AM in T)
|
||||
if(next_floor == floors[floors.len])
|
||||
AM.crush_act()
|
||||
@@ -108,7 +108,9 @@
|
||||
origin.move_contents_to(destination)
|
||||
for(var/thing in move_candidates)
|
||||
var/atom/movable/AM = thing
|
||||
AM.forceMove(GET_ABOVE(AM))
|
||||
var/turf/T = get_turf(AM)
|
||||
if(istype(T))
|
||||
AM.forceMove(GET_TURF_ABOVE(T))
|
||||
|
||||
current_floor = next_floor
|
||||
control_panel_interior.visible_message("The elevator [moving_upwards ? "rises" : "descends"] smoothly.")
|
||||
|
||||
@@ -268,7 +268,7 @@
|
||||
blastdoor_interact(TRUE)
|
||||
return
|
||||
|
||||
var/turf/aboveturf = GetAbove(A)
|
||||
var/turf/aboveturf = GET_TURF_ABOVE(A)
|
||||
if(aboveturf)
|
||||
applyfalldamage(aboveturf)
|
||||
aboveturf.ChangeTurf(/turf/simulated/floor/foamedmetal)
|
||||
@@ -287,7 +287,7 @@
|
||||
set_light(5,1,LIGHT_COLOR_EMERGENCY_SOFT)
|
||||
A.visible_message(SPAN_DANGER("\The [src] crashes through the roof!"))
|
||||
|
||||
var/turf/belowturf = GetBelow(A)
|
||||
var/turf/belowturf = GET_TURF_BELOW(A)
|
||||
if(belowturf)
|
||||
belowturf.visible_message(SPAN_DANGER("You hear something crash into the ceiling above!"))
|
||||
status = USED
|
||||
|
||||
@@ -28,8 +28,8 @@
|
||||
return
|
||||
|
||||
var/turf/T = get_turf(usr)
|
||||
while(T && HasAbove(T.z))
|
||||
T = GetAbove(T)
|
||||
while(T && GET_TURF_ABOVE(T))
|
||||
T = GET_TURF_ABOVE(T)
|
||||
if(!istype(T))
|
||||
to_chat(usr, SPAN_WARNING("You need to have a turf to use this verb."))
|
||||
return
|
||||
|
||||
@@ -28,7 +28,7 @@ INITIALIZE_IMMEDIATE(/obj/abstract/weather_system)
|
||||
// Track all z-levels.
|
||||
for(var/highest_z in affecting_zs)
|
||||
var/turfcount = 0
|
||||
if(HasAbove(highest_z))
|
||||
if(SSmapping.multiz_levels[highest_z][Z_LEVEL_UP])
|
||||
continue
|
||||
// Update turf weather.
|
||||
for(var/turf/T as anything in block(locate(1, 1, highest_z), locate(world.maxx, world.maxy, highest_z)))
|
||||
|
||||
Reference in New Issue
Block a user