[MIRROR] Multi-Z Support for Lazy Templates | Cleans up some turf flag misuse [MDB IGNORE] (#23794)

* Multi-Z Support for Lazy Templates | Cleans up some turf flag misuse

* Update hilbertshotel.dm

* Modular proc ref

---------

Co-authored-by: Zephyr <12817816+ZephyrTFA@users.noreply.github.com>
Co-authored-by: Bloop <13398309+vinylspiders@users.noreply.github.com>
This commit is contained in:
SkyratBot
2023-09-19 13:26:14 -04:00
committed by GitHub
co-authored by Zephyr Bloop
parent 4fa7c51670
commit d9624bdf97
38 changed files with 1054 additions and 191 deletions
@@ -1,4 +1,10 @@
//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
"aa" = (
/turf/open/water,
/area/awaymission/beach)
"ab" = (
/turf/open/lava,
/area/awaymission/caves)
"bX" = (
/turf/closed/indestructible/abductor{
icon_state = "alien11"
@@ -592,3 +598,515 @@ bX
Zf
Xy
"}
(1,1,2) = {"
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
"}
(2,1,2) = {"
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
"}
(3,1,2) = {"
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
"}
(4,1,2) = {"
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
"}
(5,1,2) = {"
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
"}
(6,1,2) = {"
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
"}
(7,1,2) = {"
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
"}
(8,1,2) = {"
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
"}
(9,1,2) = {"
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
"}
(10,1,2) = {"
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
"}
(11,1,2) = {"
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
"}
(12,1,2) = {"
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
"}
(13,1,2) = {"
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
"}
(14,1,2) = {"
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
"}
(15,1,2) = {"
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
aa
"}
(1,1,3) = {"
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
"}
(2,1,3) = {"
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
"}
(3,1,3) = {"
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
"}
(4,1,3) = {"
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
"}
(5,1,3) = {"
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
"}
(6,1,3) = {"
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
"}
(7,1,3) = {"
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
"}
(8,1,3) = {"
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
"}
(9,1,3) = {"
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
"}
(10,1,3) = {"
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
"}
(11,1,3) = {"
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
"}
(12,1,3) = {"
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
"}
(13,1,3) = {"
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
"}
(14,1,3) = {"
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
"}
(15,1,3) = {"
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
ab
"}
@@ -0,0 +1,2 @@
/// Fired on the lazy template datum when the template is finished loading. (list/loaded_atoms)
#define COMSIG_LAZY_TEMPLATE_LOADED "lazy_template_loaded"
+3
View File
@@ -88,7 +88,10 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
//TURF FLAGS
/// If a turf cant be jaunted through.
#define NOJAUNT (1<<0)
/// If a turf is an usused reservation turf awaiting assignment
#define UNUSED_RESERVATION_TURF (1<<1)
/// If a turf is a reserved turf
#define RESERVATION_TURF (1<<2)
/// Blocks lava rivers being generated on the turf.
#define NO_LAVA_GEN (1<<3)
/// Blocks ruins spawning on the turf.
+6 -2
View File
@@ -1,4 +1,8 @@
/// Attempt to get the turf below the provided one according to Z traits
#define GET_TURF_BELOW(turf) ((!(turf) || !length(SSmapping.multiz_levels) || !SSmapping.multiz_levels[(turf).z][Z_LEVEL_DOWN]) ? null : get_step((turf), DOWN))
#define GET_TURF_BELOW(turf) ( \
(turf.turf_flags & RESERVATION_TURF) ? SSmapping.get_reservation_from_turf(turf)?.get_turf_below(turf) : \
(!(turf) || !length(SSmapping.multiz_levels) || !SSmapping.multiz_levels[(turf).z][Z_LEVEL_DOWN]) ? null : get_step((turf), DOWN))
/// Attempt to get the turf above the provided one according to Z traits
#define GET_TURF_ABOVE(turf) ((!(turf) || !length(SSmapping.multiz_levels) || !SSmapping.multiz_levels[(turf).z][Z_LEVEL_UP]) ? null : get_step((turf), UP))
#define GET_TURF_ABOVE(turf) ( \
(turf.turf_flags & RESERVATION_TURF) ? SSmapping.get_reservation_from_turf(turf)?.get_turf_above(turf) : \
(!(turf) || !length(SSmapping.multiz_levels) || !SSmapping.multiz_levels[(turf).z][Z_LEVEL_UP]) ? null : get_step((turf), UP))
+1
View File
@@ -75,6 +75,7 @@ DEFINE_BITFIELD(turf_flags, list(
"NOJAUNT" = NOJAUNT,
"IS_SOLID" = IS_SOLID,
"UNUSED_RESERVATION_TURF" = UNUSED_RESERVATION_TURF,
"RESERVATION_TURF" = RESERVATION_TURF,
))
DEFINE_BITFIELD(car_traits, list(
+3
View File
@@ -127,6 +127,9 @@ GLOBAL_LIST_EMPTY(emergencyresponseteamspawn)
GLOBAL_LIST_EMPTY(ruin_landmarks)
GLOBAL_LIST_EMPTY(bar_areas)
/// List of all the maps that have been cached for /proc/load_map
GLOBAL_LIST_EMPTY(cached_maps)
/// Away missions
GLOBAL_LIST_EMPTY(vr_spawnpoints)
+23 -11
View File
@@ -190,7 +190,7 @@ SUBSYSTEM_DEF(mapping)
unused_turfs["[T.z]"] |= T
var/area/old_area = T.loc
old_area.turfs_to_uncontain += T
T.flags_1 |= UNUSED_RESERVATION_TURF
T.turf_flags = UNUSED_RESERVATION_TURF
world_contents += T
world_turf_contents += T
packet.len--
@@ -309,6 +309,10 @@ SUBSYSTEM_DEF(mapping)
returning += M
qdel(T, TRUE)
/datum/controller/subsystem/mapping/proc/get_reservation_from_turf(turf/T)
RETURN_TYPE(/datum/turf_reservation)
return used_turfs[T]
/* Nuke threats, for making the blue tiles on the station go RED
Used by the AI doomsday and the self-destruct nuke.
*/
@@ -695,26 +699,34 @@ GLOBAL_LIST_EMPTY(the_station_areas)
num_of_res_levels++
return add_new_zlevel("Transit/Reserved #[num_of_res_levels]", list(ZTRAIT_RESERVED = TRUE))
/datum/controller/subsystem/mapping/proc/RequestBlockReservation(width, height, z, type = /datum/turf_reservation, turf_type_override)
UNTIL((!z || reservation_ready["[z]"]) && !clearing_reserved_turfs)
var/datum/turf_reservation/reserve = new type
if(turf_type_override)
/// Requests a /datum/turf_reservation based on the given width, height, and z_size. You can specify a z_reservation to use a specific z level, or leave it null to use any z level.
/datum/controller/subsystem/mapping/proc/request_turf_block_reservation(
width,
height,
z_size = 1,
z_reservation = null,
reservation_type = /datum/turf_reservation,
turf_type_override = null,
)
UNTIL((!z_reservation || reservation_ready["[z_reservation]"]) && !clearing_reserved_turfs)
var/datum/turf_reservation/reserve = new reservation_type
if(!isnull(turf_type_override))
reserve.turf_type = turf_type_override
if(!z)
if(!z_reservation)
for(var/i in levels_by_trait(ZTRAIT_RESERVED))
if(reserve.Reserve(width, height, i))
if(reserve.reserve(width, height, z_size, i))
return reserve
//If we didn't return at this point, theres a good chance we ran out of room on the exisiting reserved z levels, so lets try a new one
var/datum/space_level/newReserved = add_reservation_zlevel()
initialize_reserved_level(newReserved.z_value)
if(reserve.Reserve(width, height, newReserved.z_value))
if(reserve.reserve(width, height, z_size, newReserved.z_value))
return reserve
else
if(!level_trait(z, ZTRAIT_RESERVED))
if(!level_trait(z_reservation, ZTRAIT_RESERVED))
qdel(reserve)
return
else
if(reserve.Reserve(width, height, z))
if(reserve.reserve(width, height, z_size, z_reservation))
return reserve
QDEL_NULL(reserve)
@@ -732,7 +744,7 @@ GLOBAL_LIST_EMPTY(the_station_areas)
var/block = block(A, B)
for(var/turf/T as anything in block)
// No need to empty() these, because they just got created and are already /turf/open/space/basic.
T.flags_1 |= UNUSED_RESERVATION_TURF
T.turf_flags = UNUSED_RESERVATION_TURF
CHECK_TICK
// Gotta create these suckers if we've not done so already
+15 -4
View File
@@ -617,12 +617,18 @@ SUBSYSTEM_DEF(shuttle)
if(WEST)
transit_path = /turf/open/space/transit/west
var/datum/turf_reservation/proposal = SSmapping.RequestBlockReservation(transit_width, transit_height, null, /datum/turf_reservation/transit, transit_path)
var/datum/turf_reservation/proposal = SSmapping.request_turf_block_reservation(
transit_width,
transit_height,
1,
reservation_type = /datum/turf_reservation/transit,
turf_type_override = transit_path,
)
if(!istype(proposal))
return FALSE
var/turf/bottomleft = locate(proposal.bottom_left_coords[1], proposal.bottom_left_coords[2], proposal.bottom_left_coords[3])
var/turf/bottomleft = proposal.bottom_left_turfs[1]
// Then create a transit docking port in the middle
var/coords = M.return_coords(0, 0, dock_dir)
/* 0------2
@@ -893,10 +899,15 @@ SUBSYSTEM_DEF(shuttle)
/datum/controller/subsystem/shuttle/proc/load_template(datum/map_template/shuttle/loading_template)
. = FALSE
// Load shuttle template to a fresh block reservation.
preview_reservation = SSmapping.RequestBlockReservation(loading_template.width, loading_template.height, type = /datum/turf_reservation/transit)
preview_reservation = SSmapping.request_turf_block_reservation(
loading_template.width,
loading_template.height,
1,
reservation_type = /datum/turf_reservation/transit,
)
if(!preview_reservation)
CRASH("failed to reserve an area for shuttle template loading")
var/turf/bottom_left = TURF_FROM_COORDS_LIST(preview_reservation.bottom_left_coords)
var/turf/bottom_left = preview_reservation.bottom_left_turfs[1]
loading_template.load(bottom_left, centered = FALSE, register = FALSE)
var/affected = loading_template.get_affected_turfs(bottom_left, centered=FALSE)
@@ -75,7 +75,7 @@
/datum/symptom/heal/starlight/proc/CanTileHealDirectional(turf/turf_to_check, direction)
if(direction == UP)
turf_to_check = turf_to_check.above()
turf_to_check = GET_TURF_ABOVE(turf_to_check)
if(!turf_to_check)
return STARLIGHT_CANNOT_HEAL
var/area/area_to_check = get_area(turf_to_check)
@@ -98,9 +98,9 @@
if(istransparentturf(turf_to_check) || istype(turf_to_check, /turf/open/openspace))
// Check above or below us
if(direction == UP)
turf_to_check = turf_to_check.above()
turf_to_check = GET_TURF_ABOVE(turf_to_check)
else
turf_to_check = turf_to_check.below()
turf_to_check = GET_TURF_BELOW(turf_to_check)
// If we found a turf above or below us,
// then we can rerun the loop on the newly found turf / area
@@ -21,7 +21,7 @@
return
var/turf/checked_turf = get_turf(target)
while(!isnull(checked_turf))
checked_turf = checked_turf.above()
checked_turf = GET_TURF_ABOVE(checked_turf)
if(checked_turf?.z == user.z)
INVOKE_ASYNC(source, TYPE_PROC_REF(/obj/item, handle_openspace_click), checked_turf, user, user.CanReach(checked_turf, source), click_parameters)
break
+5 -5
View File
@@ -103,7 +103,7 @@ GLOBAL_LIST_EMPTY(pillars_by_z)
if(!holding)
return
var/turf/visual_target = to_display.above()
var/turf/visual_target = GET_TURF_ABOVE(to_display)
/// Basically, if we used to be under a non transparent turf, but are no longer in that position
/// Then we add to the transparent turf we're now under, and nuke the old object
if(!istransparentturf(visual_target))
@@ -120,7 +120,7 @@ GLOBAL_LIST_EMPTY(pillars_by_z)
turf_sources[to_display] = sources
sources |= source
var/turf/visual_target = to_display.above()
var/turf/visual_target = GET_TURF_ABOVE(to_display)
if(istransparentturf(visual_target) || isopenspaceturf(visual_target))
visual_target.vis_contents += to_display
else
@@ -142,7 +142,7 @@ GLOBAL_LIST_EMPTY(pillars_by_z)
if(holding)
qdel(holding)
else
var/turf/visual_target = to_hide.above()
var/turf/visual_target = GET_TURF_ABOVE(to_hide)
visual_target.vis_contents -= to_hide
if(!length(turf_sources) && !QDELETED(src))
@@ -201,7 +201,7 @@ GLOBAL_LIST_EMPTY(pillars_by_z)
///Updates the viscontents or underlays below this tile.
/datum/element/turf_z_transparency/proc/update_multi_z(turf/our_turf)
var/turf/below_turf = our_turf.below()
var/turf/below_turf = GET_TURF_BELOW(our_turf)
if(below_turf) // If we actually have something below us, display it.
for(var/turf/partner in range(1, below_turf))
// We use our z here to ensure the pillar is actually on our level
@@ -228,7 +228,7 @@ GLOBAL_LIST_EMPTY(pillars_by_z)
return TRUE
/datum/element/turf_z_transparency/proc/clear_multiz(turf/our_turf)
var/turf/below_turf = our_turf.below()
var/turf/below_turf = GET_TURF_BELOW(our_turf)
if(below_turf) // If we actually have something below us, we need to clear ourselves from it
for(var/turf/partner in range(1, below_turf))
// We use our z here to ensure the pillar is actually on our level
+47 -10
View File
@@ -10,8 +10,6 @@
var/key
var/map_dir = "_maps/templates/lazy_templates"
var/map_name
var/map_width
var/map_height
/datum/lazy_template/New()
reservations = list()
@@ -46,25 +44,64 @@
if(!load_path || !fexists(load_path))
CRASH("lazy template [type] has an invalid load_path: '[load_path]', check directory and map name!")
var/datum/map_template/loading = new(path = load_path, cache = TRUE)
if(!loading.cached_map)
var/datum/parsed_map/parsed_template = load_map(
file(load_path),
measure_only = TRUE,
)
if(isnull(parsed_template.parsed_bounds))
CRASH("Failed to cache lazy template for loading: '[key]'")
var/datum/turf_reservation/reservation = SSmapping.RequestBlockReservation(loading.width, loading.height)
var/width = parsed_template.parsed_bounds[MAP_MAXX] - parsed_template.parsed_bounds[MAP_MINX] + 1
var/height = parsed_template.parsed_bounds[MAP_MAXY] - parsed_template.parsed_bounds[MAP_MINY] + 1
var/datum/turf_reservation/reservation = SSmapping.request_turf_block_reservation(
width,
height,
parsed_template.parsed_bounds[MAP_MAXZ],
)
if(!reservation)
CRASH("Failed to reserve a block for lazy template: '[key]'")
if(!loading.load(coords2turf(reservation.bottom_left_coords)))
CRASH("Failed to load lazy template: '[key]'")
reservations += reservation
var/list/my_loaded_atoms = list()
for(var/z_idx in parsed_template.parsed_bounds[MAP_MAXZ] to 1 step -1)
var/turf/bottom_left = reservation.bottom_left_turfs[z_idx]
var/turf/top_right = reservation.top_right_turfs[z_idx]
load_map(
file(load_path),
bottom_left.x,
bottom_left.y,
bottom_left.z,
z_upper = z_idx,
z_lower = z_idx,
)
var/list/to_init = list()
// turfs can never be duplicated so keep them out of the below list to optimize O(n)
var/list/turfs = list()
// areas can be duplicated but lets keep them seperate for efficiency
var/list/areas = list()
// everything else that can be duplicated, such as areas or large objects
var/list/not_turfs = list()
for(var/turf/turf as anything in block(bottom_left, top_right))
turfs += turf
areas |= get_area(turf)
for(var/thing in turf.get_all_contents())
// atoms can actually be in the contents of two or more turfs based on its icon/bound size
// see https://www.byond.com/docs/ref/index.html#/atom/var/contents
not_turfs |= thing
SSatoms.InitializeAtoms(to_init)
// we don't need to check for duplicates here
my_loaded_atoms += not_turfs
my_loaded_atoms += turfs
my_loaded_atoms += areas
SEND_SIGNAL(src, COMSIG_LAZY_TEMPLATE_LOADED, my_loaded_atoms)
reservations += reservation
return reservation
/datum/lazy_template/nukie_base
key = LAZY_TEMPLATE_KEY_NUKIEBASE
map_name = "nukie_base"
map_width = 89
map_height = 100
/datum/lazy_template/wizard_dem
key = LAZY_TEMPLATE_KEY_WIZARDDEN
@@ -40,8 +40,9 @@
return
if(mapload)
for (var/i in 1 to range)
if(!isgroundlessturf(loc) || GET_TURF_BELOW(loc))
new /obj/effect/decal/cleanable/xenoblood/xsplatter(loc)
var/turf/my_turf = get_turf(src)
if(!isgroundlessturf(my_turf) || GET_TURF_BELOW(my_turf))
new /obj/effect/decal/cleanable/xenoblood/xsplatter(my_turf)
if (!step_to(src, get_step(src, direction), 0))
break
return
@@ -159,8 +159,9 @@
return
if(mapload)
for (var/i in 1 to range)
if(!isgroundlessturf(loc) || GET_TURF_BELOW(loc))
new /obj/effect/decal/cleanable/blood/splatter(loc)
var/turf/my_turf = get_turf(src)
if(!isgroundlessturf(my_turf) || GET_TURF_BELOW(my_turf))
new /obj/effect/decal/cleanable/blood/splatter(my_turf)
if (!step_to(src, get_step(src, direction), 0))
break
return
@@ -25,8 +25,9 @@
return
if(mapload)
for (var/i in 1 to range)
if(prob(40) && (!isgroundlessturf(loc) || GET_TURF_BELOW(loc)))
new /obj/effect/decal/cleanable/oil/streak(loc)
var/turf/my_turf = get_turf(src)
if(prob(40) && (!isgroundlessturf(my_turf) || GET_TURF_BELOW(my_turf)))
new /obj/effect/decal/cleanable/oil/streak(my_turf)
if (!step_to(src, get_step(src, direction), 0))
break
return
+1 -1
View File
@@ -83,7 +83,7 @@
return
var/area/destination_area = newloc.loc
movedelay = world.time + movespeed
if(newloc.flags_1 & NOJAUNT)
if(newloc.turf_flags & NOJAUNT)
to_chat(user, span_warning("Some strange aura is blocking the way."))
return
if(destination_area.area_flags & NOTELEPORT || SSmapping.level_trait(newloc.z, ZTRAIT_NOPHASE))
+4 -4
View File
@@ -34,11 +34,11 @@
return
if(target.is_blocked_turf(exclude_mobs = TRUE))
return
var/turf/above = GET_TURF_ABOVE(user)
var/turf/user_turf = get_turf(user)
var/turf/above = GET_TURF_ABOVE(user_turf)
if(!isopenspaceturf(above) || !above.Adjacent(target)) //are we below a hole, is the target blocked, is the target adjacent to our hole
balloon_alert(user, "blocked!")
return
var/turf/user_turf = get_turf(user)
var/away_dir = get_dir(above, target)
user.visible_message(span_notice("[user] begins climbing upwards with [src]."), span_notice("You get to work on properly hooking [src] and going upwards."))
playsound(target, 'sound/effects/picaxe1.ogg', 50) //plays twice so people above and below can hear
@@ -47,11 +47,11 @@
if(do_after(user, climb_time, target))
user.Move(target)
uses--
if(uses <= 0)
user.visible_message(span_warning("[src] snaps and tears apart!"))
qdel(src)
QDEL_LIST(effects)
/obj/item/climbing_hook/emergency
+2
View File
@@ -105,7 +105,9 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list(
//We do this here so anything that doesn't want to persist can clear itself
var/list/old_listen_lookup = _listen_lookup?.Copy()
var/list/old_signal_procs = _signal_procs?.Copy()
var/carryover_turf_flags = (RESERVATION_TURF | UNUSED_RESERVATION_TURF) & turf_flags
var/turf/new_turf = new path(src)
new_turf.turf_flags |= carryover_turf_flags
// WARNING WARNING
// Turfs DO NOT lose their signals when they get replaced, REMEMBER THIS
+2 -1
View File
@@ -235,7 +235,8 @@ GLOBAL_LIST_EMPTY(dug_up_basalt)
turf_flags = CAN_BE_DIRTY_1 | IS_SOLID | NO_RUST | NO_RUINS
/turf/open/misc/asteroid/snow/icemoon/do_not_scrape
turf_flags = CAN_BE_DIRTY_1 | IS_SOLID | NO_RUST | NO_CLEARING
flags_1 = CAN_BE_DIRTY_1
turf_flags = IS_SOLID | NO_RUST | NO_CLEARING
/turf/open/lava/plasma/ice_moon
initial_gas_mix = ICEMOON_DEFAULT_ATMOS
+1 -1
View File
@@ -179,7 +179,7 @@
/turf/open/openspace/icemoon/Initialize(mapload)
. = ..()
var/turf/T = below()
var/turf/T = GET_TURF_BELOW(src)
//I wonder if I should error here
if(!T)
return
+1 -1
View File
@@ -4,7 +4,7 @@
icon_state = "black"
dir = SOUTH
baseturfs = /turf/open/space/transit
flags_1 = NOJAUNT //This line goes out to every wizard that ever managed to escape the den. I'm sorry.
turf_flags = NOJAUNT //This line goes out to every wizard that ever managed to escape the den. I'm sorry.
explosive_resistance = INFINITY
/turf/open/space/transit/Initialize(mapload)
+11 -7
View File
@@ -399,31 +399,35 @@ GLOBAL_VAR(restart_counter)
else
hub_password = "SORRYNOPASSWORD"
// If this is called as a part of maploading you cannot call it on the newly loaded map zs, because those get handled later on in the pipeline
/world/proc/increaseMaxX(new_maxx, max_zs_to_load = maxz)
/**
* Handles incresing the world's maxx var and intializing the new turfs and assigning them to the global area.
* If map_load_z_cutoff is passed in, it will only load turfs up to that z level, inclusive.
* This is because maploading will handle the turfs it loads itself.
*/
/world/proc/increase_max_x(new_maxx, map_load_z_cutoff = maxz)
if(new_maxx <= maxx)
return
var/old_max = world.maxx
maxx = new_maxx
if(!max_zs_to_load)
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, max_zs_to_load))
locate(maxx, maxy, map_load_z_cutoff))
global_area.contained_turfs += to_add
/world/proc/increaseMaxY(new_maxy, max_zs_to_load = maxz)
/world/proc/increase_max_y(new_maxy, map_load_z_cutoff = maxz)
if(new_maxy <= maxy)
return
var/old_maxy = maxy
maxy = new_maxy
if(!max_zs_to_load)
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, max_zs_to_load))
locate(maxx, maxy, map_load_z_cutoff))
global_area.contained_turfs += to_add
/world/proc/incrementMaxZ()
+1 -1
View File
@@ -1059,7 +1059,7 @@ GLOBAL_PROTECT(admin_verbs_poll)
if(!isobserver(usr))
admin_ghost()
usr.forceMove(coords2turf(reservation.bottom_left_coords))
usr.forceMove(reservation.bottom_left_turfs[1])
message_admins("[key_name_admin(usr)] has loaded lazy template '[choice]'")
to_chat(usr, span_boldnicegreen("Template loaded, you have been moved to the bottom left of the reservation."))
@@ -112,9 +112,10 @@ GLOBAL_VAR_INIT(hhMysteryRoomNumber, rand(1, 999999))
if(!storageTurf) //Blame subsystems for not allowing this to be in Initialize
if(!GLOB.hhStorageTurf)
var/datum/map_template/hilbertshotelstorage/storageTemp = new()
var/datum/turf_reservation/storageReservation = SSmapping.RequestBlockReservation(3, 3)
storageTemp.load(locate(storageReservation.bottom_left_coords[1], storageReservation.bottom_left_coords[2], storageReservation.bottom_left_coords[3]))
GLOB.hhStorageTurf = locate(storageReservation.bottom_left_coords[1]+1, storageReservation.bottom_left_coords[2]+1, storageReservation.bottom_left_coords[3])
var/datum/turf_reservation/storageReservation = SSmapping.request_turf_block_reservation(1, 1, 1)
var/turf/storage_turf = storageReservation.bottom_left_turfs[1]
storageTemp.load(storage_turf)
GLOB.hhStorageTurf = storage_turf
else
storageTurf = GLOB.hhStorageTurf
if(tryActiveRoom(chosenRoomNumber, target))
@@ -127,20 +128,30 @@ GLOBAL_VAR_INIT(hhMysteryRoomNumber, rand(1, 999999))
if(activeRooms["[roomNumber]"])
var/datum/turf_reservation/roomReservation = activeRooms["[roomNumber]"]
do_sparks(3, FALSE, get_turf(user))
user.forceMove(locate(roomReservation.bottom_left_coords[1] + hotelRoomTemp.landingZoneRelativeX, roomReservation.bottom_left_coords[2] + hotelRoomTemp.landingZoneRelativeY, roomReservation.bottom_left_coords[3]))
var/turf/room_bottom_left = roomReservation.bottom_left_turfs[1]
user.forceMove(locate(
room_bottom_left.x + hotelRoomTemp.landingZoneRelativeX,
room_bottom_left.y + hotelRoomTemp.landingZoneRelativeY,
room_bottom_left.z,
))
return TRUE
return FALSE
/obj/item/hilbertshotel/proc/tryStoredRoom(roomNumber, mob/user)
if(storedRooms["[roomNumber]"])
var/datum/turf_reservation/roomReservation = SSmapping.RequestBlockReservation(hotelRoomTemp.width, hotelRoomTemp.height)
hotelRoomTempEmpty.load(locate(roomReservation.bottom_left_coords[1], roomReservation.bottom_left_coords[2], roomReservation.bottom_left_coords[3]))
var/datum/turf_reservation/roomReservation = SSmapping.request_turf_block_reservation(hotelRoomTemp.width, hotelRoomTemp.height, 1)
var/turf/room_turf = roomReservation.bottom_left_turfs[1]
hotelRoomTempEmpty.load(room_turf)
var/turfNumber = 1
for(var/x in 0 to hotelRoomTemp.width-1)
for(var/y in 0 to hotelRoomTemp.height-1)
for(var/atom/movable/A in storedRooms["[roomNumber]"][turfNumber])
if(istype(A.loc, /obj/item/abstracthotelstorage))//Don't want to recall something thats been moved
A.forceMove(locate(roomReservation.bottom_left_coords[1] + x, roomReservation.bottom_left_coords[2] + y, roomReservation.bottom_left_coords[3]))
A.forceMove(locate(
room_turf.x + x,
room_turf.y + y,
room_turf.z,
))
turfNumber++
for(var/obj/item/abstracthotelstorage/S in storageTurf)
if((S.roomNumber == roomNumber) && (S.parentSphere == src))
@@ -149,29 +160,39 @@ GLOBAL_VAR_INIT(hhMysteryRoomNumber, rand(1, 999999))
activeRooms["[roomNumber]"] = roomReservation
linkTurfs(roomReservation, roomNumber)
do_sparks(3, FALSE, get_turf(user))
user.forceMove(locate(roomReservation.bottom_left_coords[1] + hotelRoomTemp.landingZoneRelativeX, roomReservation.bottom_left_coords[2] + hotelRoomTemp.landingZoneRelativeY, roomReservation.bottom_left_coords[3]))
user.forceMove(locate(
room_turf.x + hotelRoomTemp.landingZoneRelativeX,
room_turf.y + hotelRoomTemp.landingZoneRelativeY,
room_turf.z,
))
return TRUE
return FALSE
/obj/item/hilbertshotel/proc/sendToNewRoom(roomNumber, mob/user, chosen_room) //SKYRAT EDIT ADDITION - GHOST HOTEL UPDATE. Was sendToNewRoom(chosenRoomNumber, target)
var/datum/turf_reservation/roomReservation = SSmapping.RequestBlockReservation(hotelRoomTemp.width, hotelRoomTemp.height)
/obj/item/hilbertshotel/proc/sendToNewRoom(roomNumber, mob/user, chosen_room) //SKYRAT EDIT ADDITION - GHOST HOTEL UPDATE. Was sendToNewRoom(roomNumber, mob/user)
var/datum/turf_reservation/roomReservation = SSmapping.request_turf_block_reservation(hotelRoomTemp.width, hotelRoomTemp.height, 1)
var/turf/bottom_left = roomReservation.bottom_left_turfs[1]
var/datum/map_template/load_from = hotelRoomTemp
if(ruinSpawned && roomNumber == GLOB.hhMysteryRoomNumber)
hotelRoomTempLore.load(locate(roomReservation.bottom_left_coords[1], roomReservation.bottom_left_coords[2], roomReservation.bottom_left_coords[3]))
else
//SKYRAT EDIT ADDITION - GHOST HOTEL UPDATE
switch(chosen_room)
if("Apartment")
ghost_cafe_rooms_apartment.load(locate(roomReservation.bottom_left_coords[1], roomReservation.bottom_left_coords[2], roomReservation.bottom_left_coords[3]))
else
//SKYRAT EDIT END
hotelRoomTemp.load(locate(roomReservation.bottom_left_coords[1], roomReservation.bottom_left_coords[2], roomReservation.bottom_left_coords[3]))
load_from = hotelRoomTempLore
//SKYRAT EDIT ADDITION START - GHOST HOTEL UPDATE
else if(chosen_room == "Apartment")
load_from = ghost_cafe_rooms_apartment
//SKYRAT EDIT ADDITION END
load_from.load(bottom_left)
activeRooms["[roomNumber]"] = roomReservation
linkTurfs(roomReservation, roomNumber)
do_sparks(3, FALSE, get_turf(user))
user.forceMove(locate(roomReservation.bottom_left_coords[1] + hotelRoomTemp.landingZoneRelativeX, roomReservation.bottom_left_coords[2] + hotelRoomTemp.landingZoneRelativeY, roomReservation.bottom_left_coords[3]))
user.forceMove(locate(
bottom_left.x + hotelRoomTemp.landingZoneRelativeX,
bottom_left.y + hotelRoomTemp.landingZoneRelativeY,
bottom_left.z,
))
/obj/item/hilbertshotel/proc/linkTurfs(datum/turf_reservation/currentReservation, currentRoomnumber)
var/area/misc/hilbertshotel/currentArea = get_area(locate(currentReservation.bottom_left_coords[1], currentReservation.bottom_left_coords[2], currentReservation.bottom_left_coords[3]))
var/turf/room_bottom_left = currentReservation.bottom_left_turfs[1]
var/area/misc/hilbertshotel/currentArea = get_area(room_bottom_left)
currentArea.name = "Hilbert's Hotel Room [currentRoomnumber]"
currentArea.parentSphere = src
currentArea.storageTurf = storageTurf
@@ -187,9 +208,10 @@ GLOBAL_VAR_INIT(hhMysteryRoomNumber, rand(1, 999999))
if(activeRooms.len)
for(var/x in activeRooms)
var/datum/turf_reservation/room = activeRooms[x]
var/turf/room_bottom_left = room.bottom_left_turfs[1]
for(var/i in 0 to hotelRoomTemp.width-1)
for(var/j in 0 to hotelRoomTemp.height-1)
for(var/atom/movable/A in locate(room.bottom_left_coords[1] + i, room.bottom_left_coords[2] + j, room.bottom_left_coords[3]))
for(var/atom/movable/A in locate(room_bottom_left.x + i, room_bottom_left.y + j, room_bottom_left.z))
if(ismob(A))
var/mob/M = A
if(M.mind)
@@ -271,7 +293,7 @@ GLOBAL_VAR_INIT(hhMysteryRoomNumber, rand(1, 999999))
icon_state = "bluespace"
base_icon_state = "bluespace"
baseturfs = /turf/open/space/bluespace
flags_1 = NOJAUNT
turf_flags = NOJAUNT
explosive_resistance = INFINITY
var/obj/item/hilbertshotel/parentSphere
@@ -437,7 +459,11 @@ GLOBAL_VAR_INIT(hhMysteryRoomNumber, rand(1, 999999))
storeRoom()
/area/misc/hilbertshotel/proc/storeRoom()
var/roomSize = (reservation.top_right_coords[1]-reservation.bottom_left_coords[1]+1)*(reservation.top_right_coords[2]-reservation.bottom_left_coords[2]+1)
var/turf/room_bottom_left = reservation.bottom_left_turfs[1]
var/turf/room_top_right = reservation.top_right_turfs[1]
var/roomSize = \
((room_top_right.x - room_bottom_left.x) + 1) * \
((room_top_right.y - room_bottom_left.y) + 1)
var/storage[roomSize]
var/turfNumber = 1
var/obj/item/abstracthotelstorage/storageObj = new(storageTurf)
@@ -447,7 +473,7 @@ GLOBAL_VAR_INIT(hhMysteryRoomNumber, rand(1, 999999))
for(var/x in 0 to parentSphere.hotelRoomTemp.width-1)
for(var/y in 0 to parentSphere.hotelRoomTemp.height-1)
var/list/turfContents = list()
for(var/atom/movable/A in locate(reservation.bottom_left_coords[1] + x, reservation.bottom_left_coords[2] + y, reservation.bottom_left_coords[3]))
for(var/atom/movable/A in locate(room_bottom_left.x + x, room_bottom_left.y + y, room_bottom_left.z))
if(ismob(A) && !isliving(A))
continue //Don't want to store ghosts
turfContents += A
+17 -2
View File
@@ -133,7 +133,15 @@
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, 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/datum/parsed_map/parsed = load_map(
file(mappath),
x,
y,
level.z_value,
no_changeturf = (SSatoms.initialized == INITIALIZATION_INSSATOMS),
place_on_top = should_place_on_top,
new_z = TRUE,
)
var/list/bounds = parsed.bounds
if(!bounds)
return FALSE
@@ -177,7 +185,14 @@
UNSETEMPTY(turf_blacklist)
parsed.turf_blacklist = turf_blacklist
if(!parsed.load(T.x, T.y, T.z, cropMap=TRUE, no_changeturf=(SSatoms.initialized == INITIALIZATION_INSSATOMS), placeOnTop=should_place_on_top))
if(!parsed.load(
T.x,
T.y,
T.z,
crop_map = TRUE,
no_changeturf = (SSatoms.initialized == INITIALIZATION_INSSATOMS),
place_on_top = should_place_on_top,
))
return
var/list/bounds = parsed.bounds
+159 -54
View File
@@ -114,26 +114,72 @@
var/turfsSkipped = 0
#endif
/datum/parsed_map/proc/copy()
// Avoids duped work just in case
build_cache()
var/datum/parsed_map/newfriend = new()
newfriend.original_path = original_path
newfriend.map_format = map_format
newfriend.key_len = key_len
newfriend.line_len = line_len
newfriend.grid_models = grid_models.Copy()
newfriend.gridSets = gridSets.Copy()
newfriend.modelCache = modelCache.Copy()
newfriend.parsed_bounds = parsed_bounds.Copy()
// Copy parsed bounds to reset to initial values
newfriend.bounds = parsed_bounds.Copy()
newfriend.turf_blacklist = turf_blacklist?.Copy()
return newfriend
//text trimming (both directions) helper macro
#define TRIM_TEXT(text) (trim_reduced(text))
/// Shortcut function to parse a map and apply it to the world.
///
/// - `dmm_file`: A .dmm file to load (Required).
/// - `x_offset`, `y_offset`, `z_offset`: Positions representign where to load the map (Optional).
/// - `cropMap`: When true, the map will be cropped to fit the existing world dimensions (Optional).
/// - `measureOnly`: When true, no changes will be made to the world (Optional).
/// - `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, 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, new_z = new_z)
return parsed
/**
* Helper and recommened way to load a map file
* - dmm_file: The path to the map file
* - x_offset: The x offset to load the map at
* - y_offset: The y offset to load the map at
* - z_offset: The z offset to load the map at
* - crop_map: If true, the map will be cropped to the world bounds
* - measure_only: If true, the map will not be loaded, but the bounds will be calculated
* - no_changeturf: If true, the map will not call /turf/AfterChange
* - x_lower: The minimum x coordinate to load
* - x_upper: The maximum x coordinate to load
* - y_lower: The minimum y coordinate to load
* - y_upper: The maximum y coordinate to load
* - z_lower: The minimum z coordinate to load
* - z_upper: The maximum z coordinate to load
* - place_on_top: Whether to use /turf/proc/PlaceOnTop rather than /turf/proc/ChangeTurf
* - new_z: If true, a new z level will be created for the map
*/
/proc/load_map(
dmm_file,
x_offset = 0,
y_offset = 0,
z_offset = 0,
crop_map = FALSE,
measure_only = FALSE,
no_changeturf = FALSE,
x_lower = -INFINITY,
x_upper = INFINITY,
y_lower = -INFINITY,
y_upper = INFINITY,
z_lower = -INFINITY,
z_upper = INFINITY,
place_on_top = FALSE,
new_z = FALSE,
)
if(!(dmm_file in GLOB.cached_maps))
GLOB.cached_maps[dmm_file] = new /datum/parsed_map(dmm_file)
var/datum/parsed_map/parsed_map = GLOB.cached_maps[dmm_file]
parsed_map = parsed_map.copy()
if(!measure_only && !isnull(parsed_map.bounds))
parsed_map.load(x_offset, y_offset, z_offset, crop_map, no_changeturf, x_lower, x_upper, y_lower, y_upper, z_lower, z_upper, place_on_top, new_z)
return parsed_map
/// Parse a map, possibly cropping it.
/datum/parsed_map/New(tfile, x_lower = -INFINITY, x_upper = INFINITY, y_lower = -INFINITY, y_upper=INFINITY, measureOnly=FALSE)
/datum/parsed_map/New(tfile, x_lower = -INFINITY, x_upper = INFINITY, y_lower = -INFINITY, y_upper=INFINITY, z_lower = -INFINITY, z_upper=INFINITY, measureOnly=FALSE)
// This proc sleeps for like 6 seconds. why?
// Is it file accesses? if so, can those be done ahead of time, async to save on time here? I wonder.
// Love ya :)
@@ -184,20 +230,26 @@
CRASH("Coords before model definition in DMM")
var/curr_x = text2num(regexOutput[3])
if(curr_x < x_lower || curr_x > x_upper)
continue
var/curr_y = text2num(regexOutput[4])
if(curr_y < y_lower || curr_y > y_upper)
continue
var/curr_z = text2num(regexOutput[5])
if(curr_z < z_lower || curr_z > z_upper)
continue
var/datum/grid_set/gridSet = new
gridSet.xcrd = curr_x
//position of the currently processed square
gridSet.ycrd = text2num(regexOutput[4])
gridSet.zcrd = text2num(regexOutput[5])
gridSet.ycrd = curr_y
gridSet.zcrd = curr_z
bounds[MAP_MINX] = min(bounds[MAP_MINX], curr_x)
bounds[MAP_MINZ] = min(bounds[MAP_MINZ], gridSet.zcrd)
bounds[MAP_MAXZ] = max(bounds[MAP_MAXZ], gridSet.zcrd)
bounds[MAP_MINZ] = min(bounds[MAP_MINZ], curr_y)
bounds[MAP_MAXZ] = max(bounds[MAP_MAXZ], curr_z)
var/list/gridLines = splittext(regexOutput[6], "\n")
gridSet.gridLines = gridLines
@@ -238,16 +290,29 @@
bounds[MAP_MAXX] = clamp(bounds[MAP_MAXX], x_lower, x_upper)
bounds[MAP_MINY] = clamp(bounds[MAP_MINY], y_lower, y_upper)
bounds[MAP_MAXY] = clamp(bounds[MAP_MAXY], y_lower, y_upper)
bounds[MAP_MINZ] = clamp(bounds[MAP_MINZ], z_lower, z_upper)
bounds[MAP_MAXZ] = clamp(bounds[MAP_MAXZ], z_lower, z_upper)
parsed_bounds = src.bounds
src.key_len = key_len
src.line_len = line_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, new_z)
/// Iterates over all grid sets and returns ones with z values within the given bounds. Inclusive
/datum/parsed_map/proc/filter_grid_sets_based_on_z_bounds(lower_z, upper_z)
var/list/filtered_sets = list()
for(var/datum/grid_set/grid_set as anything in gridSets)
if(grid_set.zcrd < lower_z)
continue
if(grid_set.zcrd > upper_z)
continue
filtered_sets += grid_set
return filtered_sets
/// Load the parsed map into the world. You probably want [/proc/load_map]. Keep the signature the same.
/datum/parsed_map/proc/load(x_offset = 0, y_offset = 0, z_offset = 0, crop_map = FALSE, no_changeturf = FALSE, x_lower = -INFINITY, x_upper = INFINITY, y_lower = -INFINITY, y_upper = INFINITY, z_lower = -INFINITY, z_upper = INFINITY, place_on_top = FALSE, new_z = FALSE)
//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, new_z)
. = _load_impl(x_offset, y_offset, z_offset, crop_map, no_changeturf, x_lower, x_upper, y_lower, y_upper, z_lower, z_upper, place_on_top, new_z)
Master.StopLoadingMap()
#define MAPLOADING_CHECK_TICK \
@@ -262,7 +327,7 @@
}
// 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, new_z = FALSE)
/datum/parsed_map/proc/_load_impl(x_offset, y_offset, z_offset, crop_map, no_changeturf, x_lower, x_upper, y_lower, y_upper, z_lower, z_upper, place_on_top, new_z)
PRIVATE_PROC(TRUE)
// Tell ss atoms that we're doing maploading
// We'll have to account for this in the following tick_checks so it doesn't overflow
@@ -275,9 +340,9 @@
var/sucessful = FALSE
switch(map_format)
if(MAP_TGM)
sucessful = _tgm_load(x_offset, y_offset, z_offset, cropMap, no_changeturf, x_lower, x_upper, y_lower, y_upper, placeOnTop, new_z)
sucessful = _tgm_load(x_offset, y_offset, z_offset, crop_map, no_changeturf, x_lower, x_upper, y_lower, y_upper, z_lower, z_upper, place_on_top, new_z)
else
sucessful = _dmm_load(x_offset, y_offset, z_offset, cropMap, no_changeturf, x_lower, x_upper, y_lower, y_upper, placeOnTop, new_z)
sucessful = _dmm_load(x_offset, y_offset, z_offset, crop_map, no_changeturf, x_lower, x_upper, y_lower, y_upper, z_lower, z_upper, place_on_top, new_z)
// And we are done lads, call it off
SSatoms.map_loader_stop(REF(src))
@@ -309,7 +374,7 @@
// In the tgm format, each gridset contains 255 lines, each line representing one tile, with 255 total gridsets
// In the dmm format, each gridset contains 255 lines, each line representing one row of tiles, containing 255 * line length characters, with one gridset per z
// You can think of dmm as storing maps in rows, whereas tgm stores them in columns
/datum/parsed_map/proc/_tgm_load(x_offset, y_offset, z_offset, cropMap, no_changeturf, x_lower, x_upper, y_lower, y_upper, placeOnTop, new_z)
/datum/parsed_map/proc/_tgm_load(x_offset, y_offset, z_offset, crop_map, no_changeturf, x_lower, x_upper, y_lower, y_upper, z_lower, z_upper, place_on_top, new_z)
// setup
var/list/modelCache = build_cache(no_changeturf)
var/space_key = modelCache[SPACE_KEY]
@@ -330,12 +395,12 @@
var/relative_y = first_column.ycrd
var/highest_y = relative_y + y_relative_to_absolute
if(!cropMap && highest_y > world.maxy)
if(!crop_map && highest_y > world.maxy)
if(new_z)
// Need to avoid improperly loaded area/turf_contents
world.increaseMaxY(highest_y, max_zs_to_load = z_offset - 1)
world.increase_max_y(highest_y, map_load_z_cutoff = z_offset - 1)
else
world.increaseMaxY(highest_y)
world.increase_max_y(highest_y)
expanded_y = TRUE
// Skip Y coords that are above the smallest of the three params
@@ -345,7 +410,6 @@
var/y_starting_skip = relative_y - y_skip_above
highest_y -= y_starting_skip
// Y is the LOWEST it will ever be here, so we can easily set a threshold for how low to go
var/line_count = length(first_column.gridLines)
var/lowest_y = relative_y - (line_count - 1) // -1 because we decrement at the end of the loop, not the start
@@ -353,7 +417,7 @@
// X setup
var/x_delta_with = x_upper
if(cropMap)
if(crop_map)
// Take our smaller crop threshold yes?
x_delta_with = min(x_delta_with, world.maxx)
@@ -367,33 +431,51 @@
// If our relative x is greater then X upper, well then we've gotta limit our expansion
var/delta = max(final_x - x_delta_with, 0)
final_x -= delta
if(final_x > world.maxx && !cropMap)
if(final_x > world.maxx && !crop_map)
if(new_z)
// Need to avoid improperly loaded area/turf_contents
world.increaseMaxX(final_x, max_zs_to_load = z_offset - 1)
world.increase_max_x(final_x, map_load_z_cutoff = z_offset - 1)
else
world.increaseMaxX(final_x)
world.increase_max_x(final_x)
expanded_x = TRUE
var/lowest_x = max(x_lower, 1 - x_relative_to_absolute)
// Amount we offset the grid zcrd to get the true zcrd
var/grid_z_offset = z_offset - 1
var/z_upper_set = z_upper < INFINITY
var/z_lower_set = z_lower > -INFINITY
// We make the assumption that the last block of turfs will have the highest embedded z in it
var/highest_z = last_column.zcrd + z_offset - 1 // Lets not just make a new z level each time we increment maxz
// true max zcrd
var/map_bounds_z_max = last_column.zcrd
var/z_upper_parsed = map_bounds_z_max + z_offset - 1
if(z_upper_set)
z_upper_parsed -= map_bounds_z_max - z_upper
if(z_lower_set)
var/offset_amount = z_lower - 1
z_upper_parsed -= offset_amount
grid_z_offset -= offset_amount
var/list/target_grid_sets = gridSets
if(z_lower_set || z_upper_set) // bounds are set, filter out gridsets for z levels we don't want
target_grid_sets = filter_grid_sets_based_on_z_bounds(z_lower, z_upper)
var/z_threshold = world.maxz
if(highest_z > z_threshold && cropMap)
for(var/i in z_threshold + 1 to highest_z) //create a new z_level if needed
if(z_upper_parsed > z_threshold && crop_map)
for(var/i in z_threshold + 1 to z_upper_parsed) //create a new z_level if needed
world.incrementMaxZ()
if(!no_changeturf)
WARNING("Z-level expansion occurred without no_changeturf set, this may cause problems when /turf/AfterChange is called")
for(var/datum/grid_set/gset as anything in gridSets)
for(var/datum/grid_set/gset as anything in target_grid_sets)
var/true_xcrd = gset.xcrd + x_relative_to_absolute
// any cutoff of x means we just shouldn't iterate this gridset
if(final_x < true_xcrd || lowest_x > gset.xcrd)
continue
var/zcrd = gset.zcrd + z_offset - 1
var/zcrd = gset.zcrd + grid_z_offset
// If we're using changeturf, we disable it if we load into a z level we JUST created
var/no_afterchange = no_changeturf || zcrd > z_threshold
@@ -420,7 +502,7 @@
if(!cache)
SSatoms.map_loader_stop(REF(src))
CRASH("Undefined model key in DMM: [gset.gridLines[i]]")
build_coordinate(cache, locate(true_xcrd, ycrd, zcrd), no_afterchange, placeOnTop, new_z)
build_coordinate(cache, locate(true_xcrd, ycrd, zcrd), no_afterchange, place_on_top, new_z)
// only bother with bounds that actually exist
if(!first_found)
@@ -444,7 +526,7 @@
/// Stanrdard loading, not used in production
/// Doesn't take advantage of any tgm optimizations, which makes it slower but also more general
/// Use this if for some reason your map format is messy
/datum/parsed_map/proc/_dmm_load(x_offset, y_offset, z_offset, cropMap, no_changeturf, x_lower, x_upper, y_lower, y_upper, placeOnTop, new_z)
/datum/parsed_map/proc/_dmm_load(x_offset, y_offset, z_offset, crop_map, no_changeturf, x_lower, x_upper, y_lower, y_upper, z_lower, z_upper, place_on_top, new_z)
// setup
var/list/modelCache = build_cache(no_changeturf)
var/space_key = modelCache[SPACE_KEY]
@@ -455,23 +537,46 @@
var/y_relative_to_absolute = y_offset - 1
var/x_relative_to_absolute = x_offset - 1
var/line_len = src.line_len
for(var/datum/grid_set/gset as anything in gridSets)
// Amount we offset the grid zcrd to get the true zcrd
var/grid_z_offset = z_offset - 1
var/z_upper_set = z_upper < INFINITY
var/z_lower_set = z_lower > -INFINITY
// we now need to find the maximum z, fun!
var/map_bounds_z_max = 1
for(var/datum/grid_set/grid_set as anything in gridSets)
map_bounds_z_max = max(map_bounds_z_max, grid_set.zcrd)
var/z_upper_parsed = map_bounds_z_max + z_offset - 1
if(z_upper_set)
z_upper_parsed -= map_bounds_z_max - z_upper
if(z_lower_set)
var/offset_amount = z_lower - 1
z_upper_parsed -= offset_amount
grid_z_offset -= offset_amount
var/list/target_grid_sets = gridSets
if(z_lower_set || z_upper_set) // bounds are set, filter out gridsets for z levels we don't want
target_grid_sets = filter_grid_sets_based_on_z_bounds(z_lower, z_upper)
for(var/datum/grid_set/gset as anything in target_grid_sets)
var/relative_x = gset.xcrd
var/relative_y = gset.ycrd
var/true_xcrd = relative_x + x_relative_to_absolute
var/ycrd = relative_y + y_relative_to_absolute
var/zcrd = gset.zcrd + z_offset - 1
if(!cropMap && ycrd > world.maxy)
var/zcrd = gset.zcrd + grid_z_offset
if(!crop_map && ycrd > world.maxy)
if(new_z)
// Need to avoid improperly loaded area/turf_contents
world.increaseMaxY(ycrd, max_zs_to_load = z_offset - 1)
world.increase_max_y(ycrd, map_load_z_cutoff = z_offset - 1)
else
world.increaseMaxY(ycrd)
world.increase_max_y(ycrd)
expanded_y = TRUE
var/zexpansion = zcrd > world.maxz
var/no_afterchange = no_changeturf
if(zexpansion)
if(cropMap)
if(crop_map)
continue
else
while (zcrd > world.maxz) //create a new z_level if needed
@@ -508,7 +613,7 @@
var/x_step_count = ROUND_UP(x_target / key_len)
var/final_x = relative_x + (x_step_count - 1)
var/x_delta_with = x_upper
if(cropMap)
if(crop_map)
// Take our smaller crop threshold yes?
x_delta_with = min(x_delta_with, world.maxx)
if(final_x > x_delta_with)
@@ -517,12 +622,12 @@
x_step_count -= delta
final_x -= delta
x_target = x_step_count * key_len
if(final_x > world.maxx && !cropMap)
if(final_x > world.maxx && !crop_map)
if(new_z)
// Need to avoid improperly loaded area/turf_contents
world.increaseMaxX(final_x, max_zs_to_load = z_offset - 1)
world.increase_max_x(final_x, map_load_z_cutoff = z_offset - 1)
else
world.increaseMaxX(final_x)
world.increase_max_x(final_x)
expanded_x = TRUE
// We're gonna track the first and last pairs of coords we find
@@ -553,7 +658,7 @@
if(!cache)
SSatoms.map_loader_stop(REF(src))
CRASH("Undefined model key in DMM: [model_key]")
build_coordinate(cache, locate(xcrd, ycrd, zcrd), no_afterchange, placeOnTop, new_z)
build_coordinate(cache, locate(xcrd, ycrd, zcrd), no_afterchange, place_on_top, new_z)
// only bother with bounds that actually exist
if(!first_found)
+2 -2
View File
@@ -51,10 +51,10 @@
return central_turf
/datum/map_template/ruin/proc/place_on_isolated_level(z)
var/datum/turf_reservation/reservation = SSmapping.RequestBlockReservation(width, height, z) //Make the new level creation work with different traits.
var/datum/turf_reservation/reservation = SSmapping.request_turf_block_reservation(width, height, 1, z) //Make the new level creation work with different traits.
if(!reservation)
return
var/turf/placement = locate(reservation.bottom_left_coords[1],reservation.bottom_left_coords[2],reservation.bottom_left_coords[3])
var/turf/placement = reservation.bottom_left_turfs[1]
load(placement)
loaded++
for(var/turf/T in get_affected_turfs(placement))
@@ -1,10 +1,11 @@
/proc/get_step_multiz(ref, dir)
var/turf/us = get_turf(ref)
if(dir & UP)
dir &= ~UP
return get_step(GET_TURF_ABOVE(get_turf(ref)), dir)
return get_step(GET_TURF_ABOVE(us), dir)
if(dir & DOWN)
dir &= ~DOWN
return get_step(GET_TURF_BELOW(get_turf(ref)), dir)
return get_step(GET_TURF_BELOW(us), dir)
return get_step(ref, dir)
/proc/get_dir_multiz(turf/us, turf/them)
@@ -15,27 +16,21 @@
if(us.z == them.z)
return get_dir(us, them)
else
var/turf/T = us.above()
var/turf/T = GET_TURF_ABOVE(us)
var/dir = NONE
if(T && (T.z == them.z))
dir = UP
else
T = us.below()
T = GET_TURF_BELOW(us)
if(T && (T.z == them.z))
dir = DOWN
else
return get_dir(us, them)
return (dir | get_dir(us, them))
/turf/proc/above()
return GET_TURF_ABOVE(src)
/turf/proc/below()
return GET_TURF_BELOW(src)
/proc/get_lowest_turf(atom/ref)
var/turf/us = get_turf(ref)
var/next = GET_TURF_BELOW(us)
var/turf/next = GET_TURF_BELOW(us)
while(next)
us = next
next = GET_TURF_BELOW(us)
@@ -44,7 +39,7 @@
// I wish this was lisp
/proc/get_highest_turf(atom/ref)
var/turf/us = get_turf(ref)
var/next = GET_TURF_ABOVE(us)
var/turf/next = GET_TURF_ABOVE(us)
while(next)
us = next
next = GET_TURF_ABOVE(us)
@@ -1,16 +1,33 @@
//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
/// 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
/// 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
var/bottom_left_coords[3]
var/top_right_coords[3]
/// 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/open/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
@@ -19,6 +36,9 @@
pre_cordon_distance = 7
/datum/turf_reservation/proc/Release()
bottom_left_turfs.Cut()
top_right_turfs.Cut()
var/list/reserved_copy = reserved_turfs.Copy()
SSmapping.used_turfs -= reserved_turfs
reserved_turfs = list()
@@ -36,20 +56,20 @@
INVOKE_ASYNC(SSmapping, TYPE_PROC_REF(/datum/controller/subsystem/mapping, reserve_turfs), release_turfs)
/// Attempts to calaculate and store a list of turfs around the reservation for cordoning. Returns whether a valid cordon was calculated
/datum/turf_reservation/proc/calculate_cordon_turfs(turf/BL, turf/TR)
if(BL.x < 2 || BL.y < 2 || TR.x > (world.maxx - 2) || TR.y > (world.maxy - 2))
/datum/turf_reservation/proc/calculate_cordon_turfs(turf/bottom_left, turf/top_right)
if(bottom_left.x < 2 || bottom_left.y < 2 || top_right.x > (world.maxx - 2) || top_right.y > (world.maxy - 2))
return FALSE // no space for a cordon here
var/list/possible_turfs = CORNER_OUTLINE(BL, width, height)
var/list/possible_turfs = CORNER_OUTLINE(bottom_left, width, height)
// if they're our cordon turfs, accept them
possible_turfs -= cordon_turfs
for(var/turf/cordon_turf as anything in possible_turfs)
if(!(cordon_turf.flags_1 & UNUSED_RESERVATION_TURF))
if(!(cordon_turf.turf_flags & UNUSED_RESERVATION_TURF))
return FALSE
cordon_turfs = possible_turfs
pre_cordon_turfs.Cut()
cordon_turfs |= possible_turfs
if(pre_cordon_distance)
var/turf/offset_turf = locate(BL.x + pre_cordon_distance, BL.y + pre_cordon_distance, BL.z)
var/turf/offset_turf = locate(bottom_left.x + pre_cordon_distance, bottom_left.y + pre_cordon_distance, bottom_left.z)
var/list/to_add = CORNER_OUTLINE(offset_turf, width - pre_cordon_distance * 2, height - pre_cordon_distance * 2) //we step-by-stop move inwards from the outer cordon
for(var/turf/turf_being_added as anything in to_add)
pre_cordon_turfs |= turf_being_added //add one by one so we can filter out duplicates
@@ -64,10 +84,11 @@
old_area.turfs_to_uncontain += cordon_turf
cordon_area.contained_turfs += 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)
cordon_turf.flags_1 &= ~UNUSED_RESERVATION_TURF
SSmapping.unused_turfs["[cordon_turf.z]"] -= cordon_turf
// still gets linked to us though
SSmapping.used_turfs[cordon_turf] = src
//swap the area with the pre-cordoning area
@@ -113,7 +134,8 @@
if(!HAS_TRAIT(enterer, TRAIT_FREE_HYPERSPACE_SOFTCORDON_MOVEMENT))
space_dump(source, enterer)
/datum/turf_reservation/proc/Reserve(width, height, zlevel)
/// Internal proc which handles reserving the area for the reservation.
/datum/turf_reservation/proc/_reserve_area(width, height, zlevel)
src.width = width
src.height = height
if(width > world.maxx || height > world.maxy || width < 1 || height < 1)
@@ -126,12 +148,12 @@
for(var/i in avail)
CHECK_TICK
BL = i
if(!(BL.flags_1 & UNUSED_RESERVATION_TURF))
if(!(BL.turf_flags & UNUSED_RESERVATION_TURF))
continue
if(BL.x + width > world.maxx || BL.y + height > world.maxy)
continue
TR = locate(BL.x + width - 1, BL.y + height - 1, BL.z)
if(!(TR.flags_1 & UNUSED_RESERVATION_TURF))
if(!(TR.turf_flags & UNUSED_RESERVATION_TURF))
continue
final = block(BL, TR)
if(!final)
@@ -139,7 +161,7 @@
passing = TRUE
for(var/I in final)
var/turf/checking = I
if(!(checking.flags_1 & UNUSED_RESERVATION_TURF))
if(!(checking.turf_flags & UNUSED_RESERVATION_TURF))
passing = FALSE
break
if(passing) // found a potentially valid area, now try to calculate its cordon
@@ -149,18 +171,94 @@
break
if(!passing || !istype(BL) || !istype(TR))
return FALSE
bottom_left_coords = list(BL.x, BL.y, BL.z)
top_right_coords = list(TR.x, TR.y, TR.z)
for(var/i in final)
var/turf/T = i
reserved_turfs |= T
T.flags_1 &= ~UNUSED_RESERVATION_TURF
SSmapping.unused_turfs["[T.z]"] -= T
SSmapping.used_turfs[T] = src
T.turf_flags = (T.turf_flags | RESERVATION_TURF) & ~UNUSED_RESERVATION_TURF
T.ChangeTurf(turf_type, turf_type)
bottom_left_turfs += BL
top_right_turfs += TR
return TRUE
/datum/turf_reservation/proc/reserve(width, height, z_size, z_reservation)
src.z_size = z_size
var/failed_reservation = FALSE
for(var/_ in 1 to z_size)
if(!_reserve_area(width, height, z_reservation))
failed_reservation = TRUE
break
if(failed_reservation)
Release()
return FALSE
generate_cordon()
return TRUE
/// 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)
/datum/turf_reservation/New()
LAZYADD(SSmapping.turf_reservations, src)
@@ -86,7 +86,7 @@
name = ""
icon = 'icons/misc/pic_in_pic.dmi'
icon_state = "room_background"
flags_1 = NOJAUNT
turf_flags = NOJAUNT
/turf/open/ai_visible/Initialize(mapload)
. = ..()
+1 -1
View File
@@ -187,7 +187,7 @@
var/list/turfs = list()
var/list/mobs = list()
var/blueprints = FALSE
var/clone_area = SSmapping.RequestBlockReservation(size_x * 2 + 1, size_y * 2 + 1)
var/clone_area = SSmapping.request_turf_block_reservation(size_x * 2 + 1, size_y * 2 + 1, 1)
var/width = size_x * 2 + 1
var/height = size_y * 2 + 1
@@ -16,13 +16,14 @@
var/wipe_atoms = FALSE
if(istype(clone_area) && total_x == clone_area.width && total_y == clone_area.height && size_x >= 0 && size_y > 0)
var/cloned_center_x = round(clone_area.bottom_left_coords[1] + ((total_x - 1) / 2))
var/cloned_center_y = round(clone_area.bottom_left_coords[2] + ((total_y - 1) / 2))
var/turf/bottom_left = clone_area.bottom_left_turfs[1]
var/cloned_center_x = round(bottom_left.x + ((total_x - 1) / 2))
var/cloned_center_y = round(bottom_left.y + ((total_y - 1) / 2))
for(var/t in turfs)
var/turf/T = t
var/offset_x = T.x - center.x
var/offset_y = T.y - center.y
var/turf/newT = locate(cloned_center_x + offset_x, cloned_center_y + offset_y, clone_area.bottom_left_coords[3])
var/turf/newT = locate(cloned_center_x + offset_x, cloned_center_y + offset_y, bottom_left.z)
if(!(newT in clone_area.reserved_turfs)) //sanity check so we don't overwrite other areas somehow
continue
atoms += new /obj/effect/appearance_clone(newT, T)
@@ -34,7 +35,7 @@
atoms += new /obj/effect/appearance_clone(newT, A)
skip_normal = TRUE
wipe_atoms = TRUE
center = locate(cloned_center_x, cloned_center_y, clone_area.bottom_left_coords[3])
center = locate(cloned_center_x, cloned_center_y, bottom_left.z)
if(!skip_normal)
for(var/i in turfs)
@@ -28,7 +28,18 @@
var/z_offset = SSmapping.station_start
var/list/bounds
for (var/path in SSmapping.config.GetFullMapPaths())
var/datum/parsed_map/parsed = load_map(file(path), 1, 1, z_offset, measureOnly = FALSE, no_changeturf = FALSE, cropMap=TRUE, x_lower = mother1.x_low, y_lower = mother1.y_low, x_upper = mother1.x_high, y_upper = mother1.y_high)
var/datum/parsed_map/parsed = load_map(
file(path),
1,
1,
z_offset,
no_changeturf = FALSE,
crop_map = TRUE,
x_lower = mother1.x_low,
y_lower = mother1.y_low,
x_upper = mother1.x_high,
y_upper = mother1.y_high,
)
bounds = parsed?.bounds
z_offset += bounds[MAP_MAXZ] - bounds[MAP_MINZ] + 1
+3 -3
View File
@@ -21,11 +21,11 @@
return ..()
//Are we a trunk that goes up? Or down?
var/turf/target = null
var/turf/target = get_turf(src)
if(multiz_dir == MULTIZ_PIPE_UP)
target = GET_TURF_ABOVE(get_turf(src))
target = GET_TURF_ABOVE(target)
if(multiz_dir == MULTIZ_PIPE_DOWN)
target = GET_TURF_BELOW(get_turf(src))
target = GET_TURF_BELOW(target)
if(!target) //Nothing located.
return
+11 -2
View File
@@ -382,8 +382,17 @@
/// This should be a unit test, but too much of our other code breaks during shuttle movement, so not yet, not yet.
/proc/test_whiteship_sizes()
var/obj/docking_port/stationary/port_type = /obj/docking_port/stationary/picked/whiteship
var/datum/turf_reservation/docking_yard = SSmapping.RequestBlockReservation(initial(port_type.width), initial(port_type.height))
var/turf/spawnpoint = locate(docking_yard.bottom_left_coords[1] + initial(port_type.dwidth), docking_yard.bottom_left_coords[2] + initial(port_type.dheight), docking_yard.bottom_left_coords[3])
var/datum/turf_reservation/docking_yard = SSmapping.request_turf_block_reservation(
initial(port_type.width),
initial(port_type.height),
1,
)
var/turf/bottom_left = docking_yard.bottom_left_turfs[1]
var/turf/spawnpoint = locate(
bottom_left.x + initial(port_type.dwidth),
bottom_left.y + initial(port_type.dheight),
bottom_left.z,
)
var/obj/docking_port/stationary/picked/whiteship/port = new(spawnpoint)
var/list/ids = port.shuttlekeys
@@ -11,15 +11,16 @@
..()
//reserve a tile that is always empty for our z destination
reserved = SSmapping.RequestBlockReservation(5,5)
reserved = SSmapping.request_turf_block_reservation(5, 5, 1)
// Create a space tile that goes to another z-level
claimed_tile = run_loc_floor_bottom_left.type
space_tile = run_loc_floor_bottom_left.ChangeTurf(/turf/open/space)
space_tile.destination_x = round(reserved.bottom_left_coords[1] + (reserved.width-1) / 2)
space_tile.destination_y = round(reserved.bottom_left_coords[2] + (reserved.height-1) / 2)
space_tile.destination_z = reserved.bottom_left_coords[3]
var/turf/bottom_left = reserved.bottom_left_turfs[1]
space_tile.destination_x = round(bottom_left.x + (reserved.width-1) / 2)
space_tile.destination_y = round(bottom_left.y + (reserved.height-1) / 2)
space_tile.destination_z = bottom_left.z
// Create our list of humans, all adjacent to one another
alice = new(locate(run_loc_floor_bottom_left.x + 2, run_loc_floor_bottom_left.y, run_loc_floor_bottom_left.z))
@@ -9,7 +9,7 @@
for(var/obj/structure/flora/plant in contents)
qdel(plant)
var/turf/T = below()
var/turf/T = GET_TURF_BELOW(src)
if(T)
if(T.turf_flags & NO_RUINS)
ChangeTurf(replacement_turf, null, CHANGETURF_IGNORE_AIR)
+1
View File
@@ -300,6 +300,7 @@
#include "code\__DEFINES\dcs\signals\signals_janitor.dm"
#include "code\__DEFINES\dcs\signals\signals_key.dm"
#include "code\__DEFINES\dcs\signals\signals_ladder.dm"
#include "code\__DEFINES\dcs\signals\signals_lazy_templates.dm"
#include "code\__DEFINES\dcs\signals\signals_leash.dm"
#include "code\__DEFINES\dcs\signals\signals_lift.dm"
#include "code\__DEFINES\dcs\signals\signals_light_eater.dm"