Merge pull request #4764 from Citadel-Station-13/upstream-merge-34090

[MIRROR] Replace hardcoded z-level numbers with a trait system
This commit is contained in:
deathride58
2018-01-12 17:41:28 +00:00
committed by GitHub
24 changed files with 517 additions and 366 deletions
+63 -2
View File
@@ -45,7 +45,8 @@ GLOBAL_LIST_INIT(admin_verbs_debug_mapping, list(
/client/proc/start_line_profiling,
/client/proc/stop_line_profiling,
/client/proc/show_line_profiling,
/client/proc/create_mapping_job_icons
/client/proc/create_mapping_job_icons,
/client/proc/debug_z_levels,
))
/obj/effect/debugging/mapfix_marker
@@ -292,4 +293,64 @@ GLOBAL_VAR_INIT(say_disabled, FALSE)
//Also add the x
for(var/x_number in 1 to 4)
final.Insert(icon('icons/mob/screen_gen.dmi', "x[x_number == 1 ? "" : x_number]"), "x[x_number == 1 ? "" : x_number]")
fcopy(final, "icons/mob/landmarks.dmi")
fcopy(final, "icons/mob/landmarks.dmi")
/client/proc/debug_z_levels()
set name = "Debug Z-Levels"
set category = "Mapping"
var/list/z_list = SSmapping.z_list
var/list/messages = list()
messages += "<b>World</b>: [world.maxx] x [world.maxy] x [world.maxz]<br>"
var/list/linked_levels = list()
var/min_x = INFINITY
var/min_y = INFINITY
var/max_x = -INFINITY
var/max_y = -INFINITY
for(var/z in 1 to max(world.maxz, z_list.len))
if (z > z_list.len)
messages += "<b>[z]</b>: Unmanaged (out of bounds)<br>"
continue
var/datum/space_level/S = z_list[z]
if (!S)
messages += "<b>[z]</b>: Unmanaged (null)<br>"
continue
var/linkage
switch (S.linkage)
if (UNAFFECTED)
linkage = "no linkage"
if (SELFLOOPING)
linkage = "self-looping"
if (CROSSLINKED)
linkage = "linked at ([S.xi], [S.yi])"
linked_levels += S
min_x = min(min_x, S.xi)
min_y = min(min_y, S.yi)
max_x = max(max_x, S.xi)
max_y = max(max_y, S.yi)
else
linkage = "unknown linkage '[S.linkage]'"
messages += "<b>[z]</b>: [S.name], [linkage], traits: [json_encode(S.traits)]<br>"
if (S.z_value != z)
messages += "-- z_value is [S.z_value], should be [z]<br>"
if (S.name == initial(S.name))
messages += "-- name not set<br>"
if (z > world.maxz)
messages += "-- exceeds max z"
var/grid[max_x - min_x + 1][max_y - min_y + 1]
for(var/datum/space_level/S in linked_levels)
grid[S.xi - min_x + 1][S.yi - min_y + 1] = S.z_value
messages += "<table border='1'>"
for(var/y in max_y to min_y step -1)
var/list/part = list()
for(var/x in min_x to max_x)
part += "[grid[x - min_x + 1][y - min_y + 1]]"
messages += "<tr><td>[part.Join("</td><td>")]</td></tr>"
messages += "</table>"
to_chat(src, messages.Join(""))
+3 -3
View File
@@ -5,12 +5,12 @@
anchored = TRUE
density = TRUE
var/question = "Travel back?"
var/list/zlevels = list()
var/list/zlevels
/obj/structure/signpost/New()
. = ..()
set_light(2)
zlevels = GLOB.station_z_levels
zlevels = SSmapping.levels_by_trait(ZTRAIT_STATION)
/obj/structure/signpost/attackby(obj/item/W, mob/user, params)
return attack_hand(user)
@@ -44,6 +44,6 @@
zlevels = list()
for(var/i in 1 to world.maxz)
zlevels += i
zlevels -= ZLEVEL_CENTCOM // no easy victory, even with meme signposts
zlevels -= SSmapping.levels_by_trait(ZTRAIT_CENTCOM) // no easy victory, even with meme signposts
// also, could you think of the horror if they ended up in a holodeck
// template or something
+4 -3
View File
@@ -32,8 +32,9 @@ In my current plan for it, 'solid' will be defined as anything with density == 1
/datum/round_event/immovable_rod/start()
var/datum/round_event_control/immovable_rod/C = control
var/startside = pick(GLOB.cardinals)
var/turf/startT = spaceDebrisStartLoc(startside, ZLEVEL_STATION_PRIMARY)
var/turf/endT = spaceDebrisFinishLoc(startside, ZLEVEL_STATION_PRIMARY)
var/z = pick(SSmapping.levels_by_trait(ZTRAIT_STATION))
var/turf/startT = spaceDebrisStartLoc(startside, z)
var/turf/endT = spaceDebrisFinishLoc(startside, z)
new /obj/effect/immovablerod(startT, endT, C.special_target)
/obj/effect/immovablerod
@@ -60,7 +61,7 @@ In my current plan for it, 'solid' will be defined as anything with density == 1
enter_link="<a href=?src=[REF(src)];orbit=1>(Click to orbit)</a>",
source=src, action=NOTIFY_ORBIT)
GLOB.poi_list += src
var/special_target_valid = FALSE
if(special_target)
var/turf/T = get_turf(special_target)
@@ -0,0 +1,14 @@
/datum/space_level
var/name = "Your config settings failed, you need to fix this for the datum space levels to work"
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, new_linkage = SELFLOOPING, list/new_traits = list())
z_value = new_z
name = new_name
traits = new_traits
set_linkage(new_linkage)
@@ -1,18 +1,6 @@
//This is a simple 3 by 3 grid working off the corpse of the space torus. The donut is dead, cube has been avenged!
GLOBAL_LIST_EMPTY(z_levels_list)
/datum/space_level
var/name = "Your config settings failed, you need to fix this for the datum space levels to work"
var/list/neigbours = list()
var/z_value = 1 //actual z placement
var/linked = SELFLOOPING
var/xi
var/yi //imaginary placements on the grid
/datum/space_level/New(transition_type)
linked = transition_type
if(linked == SELFLOOPING)
/datum/space_level/proc/set_linkage(new_linkage)
linkage = new_linkage
if(linkage == SELFLOOPING)
neigbours = list()
var/list/L = list(TEXT_NORTH,TEXT_SOUTH,TEXT_EAST,TEXT_WEST)
for(var/A in L)
@@ -69,21 +57,15 @@ GLOBAL_LIST_EMPTY(z_levels_list)
if(y-1 >= 1)
neigbours |= grid[x][y-1]
/proc/setup_map_transitions() //listamania
/datum/controller/subsystem/mapping/proc/setup_map_transitions() //listamania
var/list/SLS = list()
var/datum/space_level/D
var/list/cached_transitions = SSmapping.config.transition_config
var/conf_set_len = cached_transitions.len
var/k = 1
for(var/A in cached_transitions)
D = new(cached_transitions[A])
D.name = A
D.z_value = k
if(D.linked != CROSSLINKED)
GLOB.z_levels_list["[D.z_value]"] = D
else
var/list/cached_z_list = z_list
var/conf_set_len = 0
for(var/A in cached_z_list)
var/datum/space_level/D = A
if (D.linkage == CROSSLINKED)
SLS.Add(D)
k++
conf_set_len++
var/list/point_grid[conf_set_len*2+1][conf_set_len*2+1]
var/list/grid = list()
var/datum/space_transition_point/P
@@ -99,7 +81,7 @@ GLOBAL_LIST_EMPTY(z_levels_list)
var/list/used_points = list()
grid.Cut()
while(SLS.len)
D = pick_n_take(SLS)
var/datum/space_level/D = pick_n_take(SLS)
D.xi = P.x
D.yi = P.y
P.spl = D
@@ -108,10 +90,7 @@ GLOBAL_LIST_EMPTY(z_levels_list)
possible_points.Remove(used_points)
D.set_neigbours(used_points)
P = pick(possible_points)
grid["[D.z_value]"] = D
for(var/A in GLOB.z_levels_list)
grid[A] = GLOB.z_levels_list[A]
CHECK_TICK
//Lists below are pre-calculated values arranged in the list in such a way to be easily accessable in the loop by the counter
//Its either this or madness with lotsa math
@@ -123,13 +102,12 @@ GLOBAL_LIST_EMPTY(z_levels_list)
var/list/x_pos_transition = list(1, 1, TRANSITIONEDGE + 2, world.maxx - TRANSITIONEDGE - 2) //values of x for the transition from respective blocks on the side of zlevel, 1 is being translated into turfs respective x value later in the code
var/list/y_pos_transition = list(TRANSITIONEDGE + 2, world.maxy - TRANSITIONEDGE - 2, 1, 1) //values of y for the transition from respective blocks on the side of zlevel, 1 is being translated into turfs respective y value later in the code
for(var/zlevelnumber = 1, zlevelnumber<=grid.len, zlevelnumber++)
D = grid["[zlevelnumber]"]
if(!D)
CRASH("[zlevelnumber] position has no space level datum.")
if(!(D.neigbours.len))
for(var/I in cached_z_list)
var/datum/space_level/D = I
if(!D.neigbours.len)
continue
for(var/side = 1, side<5, side++)
var/zlevelnumber = D.z_value
for(var/side in 1 to 4)
var/turf/beginning = locate(x_pos_beginning[side], y_pos_beginning[side], zlevelnumber)
var/turf/ending = locate(x_pos_ending[side], y_pos_ending[side], zlevelnumber)
var/list/turfblock = block(beginning, ending)
@@ -143,12 +121,8 @@ GLOBAL_LIST_EMPTY(z_levels_list)
while(D.neigbours["[dirside]"] && D.neigbours["[dirside]"] != D)
D = D.neigbours["[dirside]"]
zdestination = D.z_value
D = grid["[zlevelnumber]"]
D = I
for(var/turf/open/space/S in turfblock)
S.destination_x = x_pos_transition[side] == 1 ? S.x : x_pos_transition[side]
S.destination_y = y_pos_transition[side] == 1 ? S.y : y_pos_transition[side]
S.destination_z = zdestination
//S.maptext = "[zdestination]" // for debugging
for(var/A in grid)
GLOB.z_levels_list[A] = grid[A]
@@ -0,0 +1,46 @@
// Look up levels[z].traits[trait]
/datum/controller/subsystem/mapping/proc/level_trait(z, trait)
if (!z)
return null
var/list/trait_list
if (z_list)
var/datum/space_level/S = get_level(z)
trait_list = S.traits
else
var/list/default_map_traits = DEFAULT_MAP_TRAITS
trait_list = default_map_traits[z][DL_TRAITS]
return trait_list[trait]
// Check if levels[z] has any of the specified traits
/datum/controller/subsystem/mapping/proc/level_has_any_trait(z, list/traits)
for (var/I in traits)
if (level_trait(z, I))
return TRUE
return FALSE
// Check if levels[z] has all of the specified traits
/datum/controller/subsystem/mapping/proc/level_has_all_traits(z, list/traits)
for (var/I in traits)
if (!level_trait(z, I))
return FALSE
return TRUE
// Get a list of all z which have the specified trait
/datum/controller/subsystem/mapping/proc/levels_by_trait(trait)
. = list()
var/list/_z_list = z_list
for(var/A in _z_list)
var/datum/space_level/S = A
if (S.traits[trait])
. += S.z_value
// Get a list of all z which have any of the specified traits
/datum/controller/subsystem/mapping/proc/levels_by_any_trait(list/traits)
. = list()
var/list/_z_list = z_list
for(var/A in _z_list)
var/datum/space_level/S = A
for (var/trait in traits)
if (S.traits[trait])
. += S.z_value
break
@@ -0,0 +1,32 @@
// Populate the space level list and prepare space transitions
/datum/controller/subsystem/mapping/proc/InitializeDefaultZLevels()
if (z_list) // subsystem/Recover or badminnery, no need
return
z_list = list()
var/list/default_map_traits = DEFAULT_MAP_TRAITS
if (default_map_traits.len != world.maxz)
WARNING("More or less map attributes pre-defined ([default_map_traits.len]) than existent z-levels ([world.maxz]). Ignoring the larger.")
if (default_map_traits.len > world.maxz)
default_map_traits.Cut(world.maxz + 1)
for (var/I in 1 to default_map_traits.len)
var/list/features = default_map_traits[I]
var/datum/space_level/S = new(I, features[DL_NAME], features[DL_LINKAGE], features[DL_TRAITS])
z_list += S
/datum/controller/subsystem/mapping/proc/add_new_zlevel(name, linkage = SELFLOOPING, traits = list(), z_type = /datum/space_level)
var/new_z = z_list.len + 1
if (world.maxz < new_z)
++world.maxz
CHECK_TICK
// TODO: sleep here if the Z level needs to be cleared
var/datum/space_level/S = new z_type(new_z, name, linkage, traits)
z_list += S
return new_z
/datum/controller/subsystem/mapping/proc/get_level(z)
. = z_list[z]
if (!.)
CRASH("Unmanaged z-level: '[z]'")
+4 -1
View File
@@ -102,7 +102,10 @@ interface with the mining shuttle at the landing site if a mobile beacon is also
if(href_list["random"] && !possible_destinations)
usr.changeNext_move(CLICK_CD_RAPID) //Anti-spam
var/turf/LZ = safepick(Z_TURFS(ZLEVEL_MINING)) //Pick a random mining Z-level turf
var/list/all_mining_turfs = list()
for (var/z_level in SSmapping.levels_by_trait(ZTRAIT_MINING))
all_mining_turfs += Z_TURFS(z_level)
var/turf/LZ = safepick(all_mining_turfs) //Pick a random mining Z-level turf
if(!ismineralturf(LZ) && !istype(LZ, /turf/open/floor/plating/asteroid))
//Find a suitable mining turf. Reduces chance of landing in a bad area
to_chat(usr, "<span class='warning'>Landing zone scan failed. Please try again.</span>")
@@ -1,6 +1,6 @@
/datum/mapGenerator/lavaland
var/start_z = ZLEVEL_LAVALAND
var/start_z
var/min_x = 0
var/min_y = 0
var/max_x = 0
@@ -19,11 +19,9 @@
/datum/mapGeneratorModule/river
var/river_type = /turf/open/lava/smooth
var/river_nodes = 4
var/start_z = ZLEVEL_LAVALAND
/datum/mapGeneratorModule/river/generate()
var/datum/mapGenerator/lavaland/L = mother
if(!istype(L))
return
start_z = L.start_z
spawn_rivers(start_z, river_nodes, river_type, min_x = L.min_x, min_y = L.min_y, max_x = L.max_x, max_y = L.max_y)
spawn_rivers(L.start_z, river_nodes, river_type, min_x = L.min_x, min_y = L.min_y, max_x = L.max_x, max_y = L.max_y)