mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-08-22 19:47:22 +01:00
Makes space level removal and adding smooth
This commit is contained in:
@@ -32,6 +32,7 @@
|
||||
..()
|
||||
var/datum/space_level/S = space_manager.get_zlev(z)
|
||||
S.add_to_transit(src)
|
||||
S.apply_transition(src)
|
||||
|
||||
/turf/space/proc/update_starlight()
|
||||
if(!config.starlight)
|
||||
@@ -209,3 +210,26 @@
|
||||
|
||||
/turf/space/can_have_cabling()
|
||||
return 0
|
||||
|
||||
/turf/space/proc/set_transition_north(dest_z)
|
||||
destination_x = x
|
||||
destination_y = TRANSITIONEDGE + 2
|
||||
destination_z = dest_z
|
||||
|
||||
/turf/space/proc/set_transition_south(dest_z)
|
||||
destination_x = x
|
||||
destination_y = world.maxy - TRANSITIONEDGE - 2
|
||||
destination_z = dest_z
|
||||
|
||||
/turf/space/proc/set_transition_east(dest_z)
|
||||
destination_x = TRANSITIONEDGE + 2
|
||||
destination_y = y
|
||||
destination_z = dest_z
|
||||
|
||||
/turf/space/proc/set_transition_west(dest_z)
|
||||
destination_x = world.maxx - TRANSITIONEDGE - 2
|
||||
destination_y = y
|
||||
destination_z = dest_z
|
||||
|
||||
/turf/space/proc/remove_transitions()
|
||||
destination_z = initial(destination_z)
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
// Map transition stuff
|
||||
var/list/neighbors = list()
|
||||
// # How this level connects with others. See __MAP_DEFINES.dm for defines
|
||||
var/linkage = SELFLOOPING
|
||||
// It's UNAFFECTED by default because none of the space turfs are normally linked up
|
||||
// so we don't need to rebuild transitions if an UNAFFECTED level is requested
|
||||
var/linkage = UNAFFECTED
|
||||
// # imaginary placements on the grid - these reflect the point it is linked to
|
||||
var/xi
|
||||
var/yi
|
||||
@@ -21,15 +23,35 @@
|
||||
|
||||
/datum/space_level/New(z, name, transition_type = SELFLOOPING)
|
||||
zpos = z
|
||||
set_linkage(transition_type)
|
||||
build_space_destination_arrays()
|
||||
set_linkage(transition_type)
|
||||
|
||||
/datum/space_level/Destroy()
|
||||
if(linkage == CROSSLINKED)
|
||||
if(space_manager.linkage_map)
|
||||
remove_from_space_network(space_manager.linkage_map)
|
||||
|
||||
space_manager.unbuilt_space_transitions -= src
|
||||
space_manager.z_list -= "[zpos]"
|
||||
return ..()
|
||||
|
||||
/datum/space_level/proc/build_space_destination_arrays()
|
||||
var/timer = start_watch()
|
||||
log_debug("Starting to build space destination arrays for z level '[zpos]'...")
|
||||
for(var/turf/space/S in get_turfs())
|
||||
add_to_transit(S)
|
||||
log_debug("Building space destination arrays complete, took [stop_watch(timer)]s.")
|
||||
// We skip `add_to_transit` here because we want to skip the checks in order to save time
|
||||
// Bottom border
|
||||
for(var/turf/space/S in block(locate(1,1,zpos),locate(world.maxx,TRANSITIONEDGE+1,zpos)))
|
||||
transit_south |= S
|
||||
|
||||
// Top border
|
||||
for(var/turf/space/S in block(locate(1,world.maxy,zpos),locate(world.maxx,world.maxy - TRANSITIONEDGE - 1,zpos)))
|
||||
transit_north |= S
|
||||
|
||||
// Left border
|
||||
for(var/turf/space/S in block(locate(1,TRANSITIONEDGE+1,zpos),locate(TRANSITIONEDGE+1,world.maxy - TRANSITIONEDGE - 2,zpos)))
|
||||
transit_west |= S
|
||||
|
||||
// Right border
|
||||
for(var/turf/space/S in block(locate(world.maxx - TRANSITIONEDGE - 1,TRANSITIONEDGE+1,zpos),locate(world.maxx,world.maxy - TRANSITIONEDGE - 2,zpos)))
|
||||
transit_east |= S
|
||||
|
||||
/datum/space_level/proc/add_to_transit(turf/space/S)
|
||||
if(S.y <= TRANSITIONEDGE)
|
||||
@@ -69,13 +91,46 @@
|
||||
if(S.x >= (world.maxx - TRANSITIONEDGE - 1))
|
||||
transit_east -= S
|
||||
|
||||
/datum/space_level/proc/apply_transition(turf/space/S)
|
||||
if(src in space_manager.unbuilt_space_transitions)
|
||||
return // Let the space manager handle this one
|
||||
switch(linkage)
|
||||
if(UNAFFECTED)
|
||||
S.remove_transitions()
|
||||
if(SELFLOOPING,CROSSLINKED)
|
||||
var/datum/space_level/E = get_connection()
|
||||
if(S in transit_north)
|
||||
E = get_connection("[NORTH]")
|
||||
S.set_transition_north(E.zpos)
|
||||
if(S in transit_south)
|
||||
E = get_connection("[SOUTH]")
|
||||
S.set_transition_south(E.zpos)
|
||||
if(S in transit_east)
|
||||
E = get_connection("[EAST]")
|
||||
S.set_transition_east(E.zpos)
|
||||
if(S in transit_west)
|
||||
E = get_connection("[WEST]")
|
||||
S.set_transition_west(E.zpos)
|
||||
|
||||
|
||||
/datum/space_level/proc/get_turfs()
|
||||
return block(locate(1, 1, zpos), locate(world.maxx, world.maxy, zpos))
|
||||
|
||||
/datum/space_level/proc/set_linkage(transition_type)
|
||||
if(linkage == transition_type)
|
||||
return
|
||||
// Remove ourselves from the linkage map if we were cross-linked
|
||||
if(linkage == CROSSLINKED)
|
||||
if(space_manager.linkage_map)
|
||||
remove_from_space_network(space_manager.linkage_map)
|
||||
|
||||
space_manager.unbuilt_space_transitions |= src
|
||||
linkage = transition_type
|
||||
if(transition_type == SELFLOOPING)
|
||||
link_to_self() // `link_to_self` is defined in space_transitions.dm
|
||||
switch(transition_type)
|
||||
if(UNAFFECTED)
|
||||
reset_connections()
|
||||
if(SELFLOOPING)
|
||||
link_to_self() // `link_to_self` is defined in space_transitions.dm
|
||||
|
||||
|
||||
/datum/space_level/proc/resume_init()
|
||||
|
||||
@@ -16,8 +16,10 @@
|
||||
if(Z_LEVEL_WEST)
|
||||
return Z_LEVEL_EAST
|
||||
|
||||
/datum/space_level
|
||||
var/list/direction_cache = list()
|
||||
|
||||
// Do this before setting up new connections, or the old ones will haunt you
|
||||
/datum/space_level/proc/reset_connections()
|
||||
neighbors.Cut()
|
||||
|
||||
/datum/space_level/proc/link_to_self()
|
||||
neighbors = list()
|
||||
@@ -25,6 +27,24 @@
|
||||
for(var/A in L)
|
||||
neighbors[A] = src
|
||||
|
||||
// Only call this when the `linkage_map` is already built
|
||||
/datum/space_level/proc/add_to_space_network(datum/spacewalk_grid/SW)
|
||||
// Make sure we don't bring any noise data into the network
|
||||
reset_connections()
|
||||
xi = initial(xi)
|
||||
yi = initial(yi)
|
||||
var/datum/point/P = SW.get_empty_node()
|
||||
P.set_space_level(src)
|
||||
|
||||
/datum/space_level/proc/remove_from_space_network(datum/spacewalk_grid/SW)
|
||||
var/datum/point/P = SW.get(xi,yi)
|
||||
SW.release_node(P)
|
||||
// Only do this when we're done, or we'll trample vars needed for releasing
|
||||
// the level
|
||||
xi = initial(xi)
|
||||
yi = initial(yi)
|
||||
reset_connections()
|
||||
|
||||
// This proc takes another space level, and establishes a connection between the
|
||||
// two depending on how the `xi` and the `yi` values compare
|
||||
/datum/space_level/proc/link_levels(datum/space_level/S)
|
||||
@@ -41,26 +61,18 @@
|
||||
else // yell about evil wizards, this shouldn't happen
|
||||
log_debug("Two z levels attempted to link, but were not adjacent! Our z:([xi],[yi]). Other z:([S.xi],[S.yi])")
|
||||
|
||||
// Do this before setting up new connections, or the old ones will haunt you
|
||||
/datum/space_level/proc/reset_connections()
|
||||
neighbors.Cut()
|
||||
direction_cache.Cut()
|
||||
|
||||
// `direction` here is the direction from `src` to `S`
|
||||
/datum/space_level/proc/add_connection(datum/space_level/S, direction)
|
||||
var/oppose = get_opposite_direction(direction)
|
||||
neighbors[direction] = S
|
||||
S.neighbors[oppose] = src
|
||||
space_manager.unbuilt_space_transitions |= src
|
||||
space_manager.unbuilt_space_transitions |= S
|
||||
|
||||
|
||||
// The "direction cache" will need updating if a
|
||||
/datum/space_level/proc/get_connection(direction)
|
||||
if(direction in neighbors)
|
||||
return neighbors[direction]
|
||||
var/use_direction_cache = 0
|
||||
if(use_direction_cache)
|
||||
if(direction in direction_cache)
|
||||
return direction_cache[direction]
|
||||
|
||||
// It's in a direction that loops - so we step as far in the opposite direction to get where to wrap to
|
||||
var/datum/space_level/S = src
|
||||
@@ -70,9 +82,6 @@
|
||||
if(S.neighbors[oppose] == src) // we've got a tesseract, boys
|
||||
CRASH("Tesseract formed when routing connections between z levels. Culprit: z level '[S.zpos]' to '[src.zpos]', direction [oppose]")
|
||||
S = S.neighbors[oppose]
|
||||
|
||||
if(use_direction_cache)
|
||||
direction_cache[direction] = S
|
||||
return S
|
||||
|
||||
|
||||
@@ -145,8 +154,6 @@
|
||||
// This looks around itself to see if it has any active nodes within the cardinal directions
|
||||
/datum/point/proc/has_no_neighbors(datum/spacewalk_grid/SW)
|
||||
var/result = 1
|
||||
if(spl)
|
||||
return 1
|
||||
if(!isnull(SW.get(x+1,y)))
|
||||
result = 0
|
||||
if(!isnull(SW.get(x-1,y)))
|
||||
@@ -165,6 +172,7 @@
|
||||
var/datum/space_level/S = spl.neighbors[direction]
|
||||
var/oppose = get_opposite_direction(direction)
|
||||
S.neighbors.Remove(oppose)
|
||||
space_manager.unbuilt_space_transitions |= S
|
||||
spl.reset_connections()
|
||||
spl = initial(spl)
|
||||
|
||||
@@ -191,6 +199,14 @@
|
||||
var/datum/point/P = new(0,0)
|
||||
add_available_node(P)
|
||||
|
||||
/datum/spacewalk_grid/Destroy()
|
||||
for(var/datum/point/P in filled_nodes)
|
||||
release_node(P)
|
||||
if(available_nodes.len > 1)
|
||||
log_debug("Multiple nodes left behind after SW grid qdel: [available_nodes.len]")
|
||||
for(var/datum/point/P in available_nodes)
|
||||
log_debug("([P.x],[P.y])")
|
||||
|
||||
/datum/spacewalk_grid/proc/add_available_node(datum/point/P)
|
||||
var/hash = P.hash()
|
||||
if(hash in all_nodes)
|
||||
@@ -225,9 +241,12 @@
|
||||
for(var/datum/point/P2 in P.neighbors)
|
||||
var/isolated = P2.has_no_neighbors(src)
|
||||
if(isolated)
|
||||
available_nodes -= P2
|
||||
all_nodes -= P2.hash()
|
||||
qdel(P)
|
||||
if(!P2.spl)
|
||||
available_nodes -= P2
|
||||
all_nodes -= P2.hash()
|
||||
qdel(P)
|
||||
else
|
||||
log_debug("Isolated z level at ([P2.x],[P2.y]): [P2.spl.zpos]")
|
||||
P.deactivate()
|
||||
P.neighbors.Cut()
|
||||
|
||||
@@ -307,75 +326,75 @@
|
||||
// `grid` is a flat list of these same above points
|
||||
|
||||
// Each point represents a possible z level position
|
||||
var/datum/spacewalk_grid/point_grid = new
|
||||
// We do this so we can display the way the levels connect later
|
||||
linkage_map = point_grid
|
||||
var/datum/point/P
|
||||
if(linkage_map)
|
||||
qdel(linkage_map)
|
||||
linkage_map = new
|
||||
|
||||
// Now, we pop entries in a random order from our list of space levels
|
||||
// and assign its connections based on the grid
|
||||
while(crosslinks.len)
|
||||
D = pick(crosslinks)
|
||||
crosslinks.Remove(D)
|
||||
// We now choose a point in our imaginary grid adjacent to our current location
|
||||
P = point_grid.get_empty_node()
|
||||
// Let our z level know where in the imaginary grid it is
|
||||
// This will also handle establishing neighborship with other z levels
|
||||
P.set_space_level(D)
|
||||
// Add it to our space grid
|
||||
D.add_to_space_network(linkage_map)
|
||||
|
||||
// A heavy proc - loops through all space turfs and sets its destination
|
||||
// based on its space level's linkage
|
||||
// Takes 0.6 seconds per call on my machine - could have each z level
|
||||
// have its own space turf cache, but I don't want to complicate this more
|
||||
// than is necessary
|
||||
/datum/zlev_manager/proc/setup_space_destinations()
|
||||
// Used to loop through turfs in world, now just goes through each level's
|
||||
// transit turf cache
|
||||
/datum/zlev_manager/proc/setup_space_destinations(force_all_rebuilds = FALSE)
|
||||
var/timer = start_watch()
|
||||
log_debug("Assigning space turf destinations...")
|
||||
var/datum/space_level/D
|
||||
var/datum/space_level/E
|
||||
var/turf/space/S
|
||||
for(var/A in z_list) //Define the transistions of the z levels
|
||||
D = z_list[A]
|
||||
if(!D.neighbors.len)
|
||||
continue
|
||||
// Left border
|
||||
for(var/B in D.transit_west)
|
||||
S = B
|
||||
E = D.get_connection(Z_LEVEL_WEST)
|
||||
S.destination_z = E.zpos
|
||||
S.destination_x = world.maxx - TRANSITIONEDGE - 2
|
||||
S.destination_y = S.y
|
||||
var/list/levels_to_rebuild = unbuilt_space_transitions
|
||||
|
||||
// Right border
|
||||
for(var/B in D.transit_east)
|
||||
S = B
|
||||
E = D.get_connection(Z_LEVEL_EAST)
|
||||
S.destination_x = TRANSITIONEDGE + 2
|
||||
S.destination_y = S.y
|
||||
S.destination_z = E.zpos
|
||||
if(force_all_rebuilds)
|
||||
// Assuming we don't have like 9000 zlevels this shouldn't hurt
|
||||
levels_to_rebuild = list()
|
||||
for(var/A in z_list)
|
||||
levels_to_rebuild.Add(z_list[A])
|
||||
|
||||
// Bottom border
|
||||
for(var/B in D.transit_south)
|
||||
S = B
|
||||
E = D.get_connection(Z_LEVEL_SOUTH)
|
||||
S.destination_x = S.x
|
||||
S.destination_y = world.maxy - TRANSITIONEDGE - 2
|
||||
S.destination_z = E.zpos
|
||||
|
||||
// Top border
|
||||
for(var/B in D.transit_north)
|
||||
S = B
|
||||
E = D.get_connection(Z_LEVEL_NORTH)
|
||||
S.destination_x = S.x
|
||||
S.destination_y = TRANSITIONEDGE + 2
|
||||
S.destination_z = E.zpos
|
||||
for(var/foo in levels_to_rebuild) //Define the transitions of the z levels
|
||||
D = foo
|
||||
log_debug("Z level [D.zpos]")
|
||||
switch(D.linkage)
|
||||
if(UNAFFECTED)
|
||||
for(var/B in D.transit_west | D.transit_east | D.transit_south | D.transit_north)
|
||||
S = B
|
||||
S.remove_transitions()
|
||||
if(SELFLOOPING,CROSSLINKED)
|
||||
// Left border
|
||||
for(var/B in D.transit_west)
|
||||
S = B
|
||||
E = D.get_connection(Z_LEVEL_WEST)
|
||||
S.set_transition_west(E.zpos)
|
||||
|
||||
// Right border
|
||||
for(var/B in D.transit_east)
|
||||
S = B
|
||||
E = D.get_connection(Z_LEVEL_EAST)
|
||||
S.set_transition_east(E.zpos)
|
||||
|
||||
// Bottom border
|
||||
for(var/B in D.transit_south)
|
||||
S = B
|
||||
E = D.get_connection(Z_LEVEL_SOUTH)
|
||||
S.set_transition_south(E.zpos)
|
||||
|
||||
// Top border
|
||||
for(var/B in D.transit_north)
|
||||
S = B
|
||||
E = D.get_connection(Z_LEVEL_NORTH)
|
||||
S.set_transition_north(E.zpos)
|
||||
unbuilt_space_transitions -= D
|
||||
|
||||
log_debug("Assigning space turf destinations complete. Took [stop_watch(timer)]s.")
|
||||
|
||||
// Nothing fancy, just does it all at once
|
||||
/datum/zlev_manager/proc/do_transition_setup()
|
||||
route_linkage()
|
||||
setup_space_destinations()
|
||||
setup_space_destinations(force_all_rebuilds = TRUE)
|
||||
|
||||
// A debugging proc that expresses the map's shape as a bunch of turfs
|
||||
/datum/zlev_manager/proc/map_as_turfs(turf/center)
|
||||
|
||||
@@ -5,6 +5,9 @@ var/global/datum/zlev_manager/space_manager = new
|
||||
var/list/z_list = list()
|
||||
var/list/heaps = list()
|
||||
|
||||
// Levels that need their transitions rebuilt
|
||||
var/list/unbuilt_space_transitions = list()
|
||||
|
||||
var/datum/spacewalk_grid/linkage_map
|
||||
|
||||
// Populate our space level list
|
||||
|
||||
Reference in New Issue
Block a user