mirror of
https://github.com/Citadel-Station-13/Citadel-Station-13-RP.git
synced 2026-08-17 17:06:47 +01:00
tl;dr level collections that can easily be logically restructured/moved as necessary will eventually be used for radio and overmaps location resolution. this is the last part of https://github.com/Citadel-Station-13/Citadel-Station-13-RP/pull/4841 that has not yet been integrated. this will be a draft for a while. --------- Co-authored-by: LetterN <24603524+LetterN@users.noreply.github.com>
178 lines
5.9 KiB
Plaintext
178 lines
5.9 KiB
Plaintext
//* This file is explicitly licensed under the MIT license. *//
|
|
//* Copyright (c) 2024 Citadel Station Developers *//
|
|
|
|
/**
|
|
* Contains loading / unloading logic.
|
|
*/
|
|
|
|
//* Loading *//
|
|
|
|
/**
|
|
* anything to do immediately on load
|
|
*
|
|
* called after level on_loaded_immediate's
|
|
*/
|
|
/datum/map/proc/on_loaded_immediate()
|
|
SHOULD_CALL_PARENT(TRUE)
|
|
|
|
loaded = TRUE
|
|
loaded_z_indices = list()
|
|
loaded_z_grid = list()
|
|
loaded_z_stacks = list()
|
|
loaded_z_planes = list()
|
|
|
|
var/struct_min_x = INFINITY
|
|
var/struct_min_y = INFINITY
|
|
var/struct_min_z = INFINITY
|
|
var/struct_max_x = -INFINITY
|
|
var/struct_max_y = -INFINITY
|
|
var/struct_max_z = -INFINITY
|
|
|
|
var/list/elevation_by_z_str = list()
|
|
|
|
// gather level data for loaded lists, and give levels virtual alignment here
|
|
for(var/idx in 1 to length(levels))
|
|
var/datum/map_level/level = levels[idx]
|
|
loaded_z_indices += level.z_index
|
|
|
|
if(!level.struct_active)
|
|
continue
|
|
loaded_z_grid["[level.struct_x],[level.struct_y],[level.struct_z]"] = level
|
|
|
|
struct_min_x = min(struct_min_x, level.struct_x)
|
|
struct_max_x = max(struct_max_x, level.struct_x)
|
|
struct_min_y = min(struct_min_y, level.struct_y)
|
|
struct_max_y = max(struct_max_y, level.struct_y)
|
|
struct_min_z = min(struct_min_z, level.struct_z)
|
|
struct_max_z = max(struct_max_z, level.struct_z)
|
|
|
|
var/x_y_str = "[level.struct_x],[level.struct_y]"
|
|
if(!loaded_z_stacks[x_y_str])
|
|
loaded_z_stacks[x_y_str] = list()
|
|
loaded_z_stacks[x_y_str] += level
|
|
|
|
var/z_str = "[level.struct_z]"
|
|
if(!loaded_z_planes[z_str])
|
|
loaded_z_planes[z_str] = list()
|
|
loaded_z_planes[z_str] += level
|
|
|
|
level.virtual_alignment_x = level.struct_x * (world.maxx - LEVEL_BORDER_WIDTH * 2) - LEVEL_BORDER_WIDTH
|
|
level.virtual_alignment_y = level.struct_y * (world.maxy - LEVEL_BORDER_WIDTH * 2) - LEVEL_BORDER_WIDTH
|
|
|
|
// sort z stacks
|
|
for(var/x_y_str in loaded_z_stacks)
|
|
var/list/datum/map_level/levels_in_stack = loaded_z_stacks[x_y_str]
|
|
tim_sort(levels_in_stack, /proc/cmp_map_level_struct_z_asc)
|
|
// sort z planes and gather elevations
|
|
for(var/z_str in loaded_z_planes)
|
|
var/list/datum/map_level/levels_in_plane = loaded_z_planes[z_str]
|
|
tim_sort(levels_in_plane, /proc/cmp_map_level_load_sequence)
|
|
elevation_by_z_str["[z_str]"] = levels_in_plane[1].ceiling_height || ceiling_height_default
|
|
|
|
// calculate loaded sparse size
|
|
loaded_sparse_size_x = struct_max_x - struct_min_x + 1
|
|
loaded_sparse_size_y = struct_max_y - struct_min_y + 1
|
|
loaded_sparse_size_z = struct_max_z - struct_min_z + 1
|
|
|
|
// sort elevations bottom to top
|
|
tim_sort(elevation_by_z_str, /proc/cmp_numeric_text_asc)
|
|
// convert elevations to lockstep
|
|
var/list/elevation_lockstep_indices = list()
|
|
var/list/elevation_lockstep_heights = list()
|
|
for(var/i in 1 to length(elevation_by_z_str))
|
|
var/z_str = elevation_by_z_str[i]
|
|
elevation_lockstep_indices += text2num(z_str)
|
|
elevation_lockstep_heights += elevation_by_z_str[z_str]
|
|
// compute and set elevations on levels
|
|
for(var/datum/map_level/level as anything in levels)
|
|
if(!level.struct_active)
|
|
continue
|
|
if(level.struct_z > 0)
|
|
var/index_of_first_nonnegative
|
|
var/total_height = 0
|
|
for(index_of_first_nonnegative in 1 to length(elevation_lockstep_indices))
|
|
if(elevation_lockstep_indices[index_of_first_nonnegative] >= 0)
|
|
break
|
|
var/last_virtual_z = 0
|
|
for(var/index in index_of_first_nonnegative to length(elevation_lockstep_indices))
|
|
var/virtual_z = elevation_lockstep_indices[index]
|
|
if(virtual_z != last_virtual_z)
|
|
total_height += ceiling_height_default * ((virtual_z - 1) - last_virtual_z)
|
|
// if it's on the level we're tallying to we ignore it as we don't tally ourselves
|
|
// because virtual_elevation is meters off the ground.. of the ground.
|
|
if(virtual_z == level.struct_z)
|
|
break
|
|
else if(virtual_z > level.struct_z)
|
|
CRASH("overshot level somehow?")
|
|
// tally current level
|
|
total_height += elevation_lockstep_heights[index]
|
|
// +1 to skip over the current level, which we already tallied
|
|
last_virtual_z = virtual_z + 1
|
|
level.virtual_elevation = total_height
|
|
else if(level.struct_z < 0)
|
|
var/index_of_first_negative
|
|
var/total_height = 0
|
|
for(index_of_first_negative in length(elevation_lockstep_indices) to 1 step -1)
|
|
if(elevation_lockstep_indices[index_of_first_negative] < 0)
|
|
break
|
|
var/last_virtual_z = 0
|
|
for(var/index in index_of_first_negative to 1 step -1)
|
|
var/virtual_z = elevation_lockstep_indices[index]
|
|
if(virtual_z != last_virtual_z)
|
|
total_height -= ceiling_height_default * (last_virtual_z - (virtual_z + 1))
|
|
// tally current level
|
|
total_height -= elevation_lockstep_heights[index]
|
|
// if we're on the level we're tallying to, we're done
|
|
if(virtual_z == level.struct_z)
|
|
break
|
|
// sanity check
|
|
else if(virtual_z < level.struct_z)
|
|
CRASH("overshot level somehow?")
|
|
level.virtual_elevation = total_height
|
|
|
|
if(overmap_initializer)
|
|
SSovermaps.initialize_entity(overmap_initializer, src)
|
|
|
|
/**
|
|
* anything to do after loading with any dependencies
|
|
*
|
|
* called after level on_loaded_finalize's
|
|
*/
|
|
/datum/map/proc/on_loaded_finalize()
|
|
SHOULD_CALL_PARENT(TRUE)
|
|
|
|
//* Unloading *//
|
|
|
|
/**
|
|
* TOOD: not hooked in yet
|
|
*
|
|
* Fired before zclear fires on the zlevels that consist of us
|
|
* * Levels have their on_unload_pre_zclear called before this.
|
|
*/
|
|
/datum/map/proc/on_unload_pre_zclear()
|
|
SHOULD_CALL_PARENT(TRUE)
|
|
|
|
/**
|
|
* TOOD: not hooked in yet
|
|
*
|
|
* Fired after zclear fires on the zlevels that consist of us
|
|
* * Levels have their on_unload_finalize called before this.
|
|
* * zlevels and then ourselves are un-referenced and/or garbage collected (if necessary) after.
|
|
*/
|
|
/datum/map/proc/on_unload_finalize()
|
|
SHOULD_CALL_PARENT(TRUE)
|
|
|
|
loaded = FALSE
|
|
loaded_z_indices = null
|
|
loaded_z_grid = null
|
|
loaded_sparse_size_x = null
|
|
loaded_sparse_size_y = null
|
|
loaded_sparse_size_z = null
|
|
loaded_z_planes = null
|
|
loaded_z_stacks = null
|
|
|
|
for(var/datum/map_level/level as anything in levels)
|
|
level.virtual_alignment_x = null
|
|
level.virtual_alignment_y = null
|
|
level.virtual_elevation = null
|