mirror of
https://github.com/yogstation13/Yogstation.git
synced 2025-02-26 09:04:50 +00:00
Backports several SSmapping improvements (#17208)
* Optimizes SSmapping * Turfs inside area are stored https://github.com/tgstation/tgstation/pull/70966 * Add async reserving of turfs * Fix bug * Fix shuttle init
This commit is contained in:
@@ -28,6 +28,8 @@
|
||||
|
||||
#define CEILING(x, y) ( -round(-(x) / (y)) * (y) )
|
||||
|
||||
#define ROUND_UP(x) ( -round(-(x)))
|
||||
|
||||
// round() acts like floor(x, 1) by default but can't handle other values
|
||||
#define FLOOR(x, y) ( round((x) / (y)) * (y) )
|
||||
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
#define CHANGETURF_DEFER_CHANGE 1
|
||||
#define CHANGETURF_IGNORE_AIR 2 // This flag prevents changeturf from gathering air from nearby turfs to fill the new turf with an approximation of local air
|
||||
#define CHANGETURF_FORCEOP 4
|
||||
#define CHANGETURF_SKIP 8 // A flag for PlaceOnTop to just instance the new turf instead of calling ChangeTurf. Used for uninitialized turfs NOTHING ELSE
|
||||
#define CHANGETURF_INHERIT_AIR 16 // Inherit air from previous turf. Implies CHANGETURF_IGNORE_AIR
|
||||
#define CHANGETURF_RECALC_ADJACENT 32 //Immediately recalc adjacent atmos turfs instead of queuing.
|
||||
10
code/__DEFINES/turfs.dm
Normal file
10
code/__DEFINES/turfs.dm
Normal file
@@ -0,0 +1,10 @@
|
||||
#define CHANGETURF_DEFER_CHANGE (1<<0)
|
||||
#define CHANGETURF_IGNORE_AIR (1<<1) // This flag prevents changeturf from gathering air from nearby turfs to fill the new turf with an approximation of local air
|
||||
#define CHANGETURF_FORCEOP (1<<2)
|
||||
#define CHANGETURF_SKIP (1<<3) // A flag for PlaceOnTop to just instance the new turf instead of calling ChangeTurf. Used for uninitialized turfs NOTHING ELSE
|
||||
#define CHANGETURF_INHERIT_AIR (1<<4) // Inherit air from previous turf. Implies CHANGETURF_IGNORE_AIR
|
||||
#define CHANGETURF_RECALC_ADJACENT (1<<5) //Immediately recalc adjacent atmos turfs instead of queuing.
|
||||
#define CHANGETURF_TRAPDOOR_INDUCED (1<<6) // Caused by a trapdoor, for trapdoor to know that this changeturf was caused by itself
|
||||
|
||||
///Returns all currently loaded turfs
|
||||
#define ALL_TURFS(...) block(locate(1, 1, 1), locate(world.maxx, world.maxy, world.maxz))
|
||||
@@ -346,6 +346,41 @@
|
||||
|
||||
return null
|
||||
|
||||
/// Takes a weighted list (see above) and expands it into raw entries
|
||||
/// This eats more memory, but saves time when actually picking from it
|
||||
/proc/expand_weights(list/list_to_pick)
|
||||
var/list/values = list()
|
||||
for(var/item in list_to_pick)
|
||||
var/value = list_to_pick[item]
|
||||
if(!value)
|
||||
continue
|
||||
values += value
|
||||
|
||||
var/gcf = greatest_common_factor(values)
|
||||
|
||||
var/list/output = list()
|
||||
for(var/item in list_to_pick)
|
||||
var/value = list_to_pick[item]
|
||||
if(!value)
|
||||
continue
|
||||
for(var/i in 1 to value / gcf)
|
||||
output += item
|
||||
return output
|
||||
|
||||
/// Takes a list of numbers as input, returns the highest value that is cleanly divides them all
|
||||
/// Note: this implementation is expensive as heck for large numbers, I only use it because most of my usecase
|
||||
/// Is < 10 ints
|
||||
/proc/greatest_common_factor(list/values)
|
||||
var/smallest = min(arglist(values))
|
||||
for(var/i in smallest to 1 step -1)
|
||||
var/safe = TRUE
|
||||
for(var/entry in values)
|
||||
if(entry % i != 0)
|
||||
safe = FALSE
|
||||
break
|
||||
if(safe)
|
||||
return i
|
||||
|
||||
/// Pick a random element from the list and remove it from the list.
|
||||
/proc/pick_n_take(list/L)
|
||||
RETURN_TYPE(L[_].type)
|
||||
|
||||
@@ -92,7 +92,9 @@ GLOBAL_LIST_INIT(typecache_powerfailure_safe_areas, typecacheof(list(/area/engin
|
||||
for(var/i in 1 to turfs.len)
|
||||
var/turf/thing = turfs[i]
|
||||
var/area/old_area = thing.loc
|
||||
old_area.turfs_to_uncontain += thing
|
||||
newA.contents += thing
|
||||
newA.contained_turfs += thing
|
||||
thing.change_area(old_area, newA)
|
||||
|
||||
newA.reg_in_areas_in_z()
|
||||
@@ -105,4 +107,101 @@ GLOBAL_LIST_INIT(typecache_powerfailure_safe_areas, typecacheof(list(/area/engin
|
||||
to_chat(creator, span_notice("You have created a new area, named [newA.name]. It is now weather proof, and constructing an APC will allow it to be powered."))
|
||||
return TRUE
|
||||
|
||||
/proc/require_area_resort()
|
||||
GLOB.sortedAreas = null
|
||||
|
||||
/// Returns a sorted version of GLOB.areas, by name
|
||||
/proc/get_sorted_areas()
|
||||
if(!GLOB.sortedAreas)
|
||||
GLOB.sortedAreas = sortTim(GLOB.areas.Copy(), /proc/cmp_name_asc)
|
||||
return GLOB.sortedAreas
|
||||
|
||||
//Takes: Area type as a text string from a variable.
|
||||
//Returns: Instance for the area in the world.
|
||||
/proc/get_area_instance_from_text(areatext)
|
||||
if(istext(areatext))
|
||||
areatext = text2path(areatext)
|
||||
return GLOB.areas_by_type[areatext]
|
||||
|
||||
//Takes: Area type as text string or as typepath OR an instance of the area.
|
||||
//Returns: A list of all areas of that type in the world.
|
||||
/proc/get_areas(areatype, subtypes=TRUE)
|
||||
if(istext(areatype))
|
||||
areatype = text2path(areatype)
|
||||
else if(isarea(areatype))
|
||||
var/area/areatemp = areatype
|
||||
areatype = areatemp.type
|
||||
else if(!ispath(areatype))
|
||||
return null
|
||||
|
||||
var/list/areas = list()
|
||||
if(subtypes)
|
||||
var/list/cache = typecacheof(areatype)
|
||||
for(var/area/area_to_check as anything in GLOB.areas)
|
||||
if(cache[area_to_check.type])
|
||||
areas += area_to_check
|
||||
else
|
||||
for(var/area/area_to_check as anything in GLOB.areas)
|
||||
if(area_to_check.type == areatype)
|
||||
areas += area_to_check
|
||||
return areas
|
||||
|
||||
/// Iterates over all turfs in the target area and returns the first non-dense one
|
||||
/proc/get_first_open_turf_in_area(area/target)
|
||||
if(!target)
|
||||
return
|
||||
for(var/turf/turf in target)
|
||||
if(!turf.density)
|
||||
return turf
|
||||
|
||||
//Takes: Area type as text string or as typepath OR an instance of the area.
|
||||
//Returns: A list of all turfs in areas of that type of that type in the world.
|
||||
/proc/get_area_turfs(areatype, target_z = 0, subtypes=FALSE)
|
||||
if(istext(areatype))
|
||||
areatype = text2path(areatype)
|
||||
else if(isarea(areatype))
|
||||
var/area/areatemp = areatype
|
||||
areatype = areatemp.type
|
||||
else if(!ispath(areatype))
|
||||
return null
|
||||
// Pull out the areas
|
||||
var/list/areas_to_pull = list()
|
||||
if(subtypes)
|
||||
var/list/cache = typecacheof(areatype)
|
||||
for(var/area/area_to_check as anything in GLOB.areas)
|
||||
if(!cache[area_to_check.type])
|
||||
continue
|
||||
areas_to_pull += area_to_check
|
||||
else
|
||||
for(var/area/area_to_check as anything in GLOB.areas)
|
||||
if(area_to_check.type != areatype)
|
||||
continue
|
||||
areas_to_pull += area_to_check
|
||||
|
||||
// Now their turfs
|
||||
var/list/turfs = list()
|
||||
for(var/area/pull_from as anything in areas_to_pull)
|
||||
var/list/our_turfs = pull_from.get_contained_turfs()
|
||||
if(target_z == 0)
|
||||
turfs += our_turfs
|
||||
else
|
||||
for(var/turf/turf_in_area as anything in our_turfs)
|
||||
if(target_z == turf_in_area.z)
|
||||
turfs += turf_in_area
|
||||
return turfs
|
||||
|
||||
|
||||
///Takes: list of area types
|
||||
///Returns: all mobs that are in an area type
|
||||
/proc/mobs_in_area_type(list/area/checked_areas)
|
||||
var/list/mobs_in_area = list()
|
||||
for(var/mob/living/mob as anything in GLOB.mob_living_list)
|
||||
if(QDELETED(mob))
|
||||
continue
|
||||
for(var/area in checked_areas)
|
||||
if(istype(get_area(mob), area))
|
||||
mobs_in_area += mob
|
||||
break
|
||||
return mobs_in_area
|
||||
|
||||
#undef BP_MAX_ROOM_SIZE
|
||||
|
||||
@@ -264,11 +264,29 @@
|
||||
|
||||
return ""
|
||||
|
||||
//Returns a string with reserved characters and spaces after the first and last letters removed
|
||||
//Like trim(), but very slightly faster. worth it for niche usecases
|
||||
/proc/trim_reduced(text)
|
||||
var/starting_coord = 1
|
||||
var/text_len = length(text)
|
||||
for (var/i in 1 to text_len)
|
||||
if (text2ascii(text, i) > 32)
|
||||
starting_coord = i
|
||||
break
|
||||
|
||||
for (var/i = text_len, i >= starting_coord, i--)
|
||||
if (text2ascii(text, i) > 32)
|
||||
return copytext(text, starting_coord, i + 1)
|
||||
|
||||
if(starting_coord > 1)
|
||||
return copytext(text, starting_coord)
|
||||
return ""
|
||||
|
||||
//Returns a string with reserved characters and spaces before the first word and after the last word removed.
|
||||
/proc/trim(text, max_length)
|
||||
if(max_length)
|
||||
text = copytext_char(text, 1, max_length)
|
||||
return trim_left(trim_right(text))
|
||||
return trim_reduced(text)
|
||||
|
||||
//Returns a string with the first element of the string capitalized.
|
||||
/proc/capitalize(t as text)
|
||||
|
||||
@@ -583,69 +583,6 @@ Turf and target are separate in case you want to teleport some distance from a t
|
||||
GLOB.sortedAreas.Add(src)
|
||||
sortTim(GLOB.sortedAreas, /proc/cmp_name_asc)
|
||||
|
||||
//Takes: Area type as a text string from a variable.
|
||||
//Returns: Instance for the area in the world.
|
||||
/proc/get_area_instance_from_text(areatext)
|
||||
if(istext(areatext))
|
||||
areatext = text2path(areatext)
|
||||
return GLOB.areas_by_type[areatext]
|
||||
|
||||
//Takes: Area type as text string or as typepath OR an instance of the area.
|
||||
//Returns: A list of all areas of that type in the world.
|
||||
/proc/get_areas(areatype, subtypes=TRUE)
|
||||
if(istext(areatype))
|
||||
areatype = text2path(areatype)
|
||||
else if(isarea(areatype))
|
||||
var/area/areatemp = areatype
|
||||
areatype = areatemp.type
|
||||
else if(!ispath(areatype))
|
||||
return null
|
||||
|
||||
var/list/areas = list()
|
||||
if(subtypes)
|
||||
var/list/cache = typecacheof(areatype)
|
||||
for(var/V in GLOB.sortedAreas)
|
||||
var/area/A = V
|
||||
if(cache[A.type])
|
||||
areas += V
|
||||
else
|
||||
for(var/V in GLOB.sortedAreas)
|
||||
var/area/A = V
|
||||
if(A.type == areatype)
|
||||
areas += V
|
||||
return areas
|
||||
|
||||
//Takes: Area type as text string or as typepath OR an instance of the area.
|
||||
//Returns: A list of all turfs in areas of that type of that type in the world.
|
||||
/proc/get_area_turfs(areatype, target_z = 0, subtypes=FALSE)
|
||||
if(istext(areatype))
|
||||
areatype = text2path(areatype)
|
||||
else if(isarea(areatype))
|
||||
var/area/areatemp = areatype
|
||||
areatype = areatemp.type
|
||||
else if(!ispath(areatype))
|
||||
return null
|
||||
|
||||
var/list/turfs = list()
|
||||
if(subtypes)
|
||||
var/list/cache = typecacheof(areatype)
|
||||
for(var/V in GLOB.sortedAreas)
|
||||
var/area/A = V
|
||||
if(!cache[A.type])
|
||||
continue
|
||||
for(var/turf/T in A)
|
||||
if(target_z == 0 || target_z == T.z)
|
||||
turfs += T
|
||||
else
|
||||
for(var/V in GLOB.sortedAreas)
|
||||
var/area/A = V
|
||||
if(A.type != areatype)
|
||||
continue
|
||||
for(var/turf/T in A)
|
||||
if(target_z == 0 || target_z == T.z)
|
||||
turfs += T
|
||||
return turfs
|
||||
|
||||
/proc/get_cardinal_dir(atom/A, atom/B)
|
||||
var/dx = abs(B.x - A.x)
|
||||
var/dy = abs(B.y - A.y)
|
||||
|
||||
@@ -45,11 +45,15 @@ GLOBAL_LIST_EMPTY(bar_areas)
|
||||
// IF YOU ARE MAKING A NEW BAR TEMPLATE AND WANT IT ROUNDSTART ADD IT TO THIS LIST!
|
||||
GLOBAL_LIST_INIT(potential_box_bars, list("Bar Trek", "Bar Spacious", "Bar Box", "Bar Casino", "Bar Citadel", "Bar Conveyor", "Bar Diner", "Bar Disco", "Bar Purple", "Bar Cheese", "Bar Grassy", "Bar Clock", "Bar Arcade"))
|
||||
|
||||
//away missions
|
||||
/// Away missions
|
||||
GLOBAL_LIST_EMPTY(awaydestinations) //a list of landmarks that the warpgate can take you to
|
||||
GLOBAL_LIST_EMPTY(vr_spawnpoints)
|
||||
|
||||
//used by jump-to-area etc. Updated by area/updateName()
|
||||
/// Just a list of all the area objects in the game
|
||||
/// Note, areas can have duplicate types
|
||||
GLOBAL_LIST_EMPTY(areas)
|
||||
/// Used by jump-to-area etc. Updated by area/updateName()
|
||||
/// If this is null, it needs to be recalculated. Use get_sorted_areas() as a getter please
|
||||
GLOBAL_LIST_EMPTY(sortedAreas)
|
||||
/// An association from typepath to area instance. Only includes areas with `unique` set.
|
||||
GLOBAL_LIST_EMPTY_TYPED(areas_by_type, /area)
|
||||
|
||||
@@ -351,7 +351,6 @@ SUBSYSTEM_DEF(air)
|
||||
queued_for_activation.Cut()
|
||||
|
||||
/datum/controller/subsystem/air/proc/setup_allturfs()
|
||||
var/list/turfs_to_init = block(locate(1, 1, 1), locate(world.maxx, world.maxy, world.maxz))
|
||||
var/list/active_turfs = src.active_turfs
|
||||
var/times_fired = ++src.times_fired
|
||||
|
||||
@@ -359,7 +358,7 @@ SUBSYSTEM_DEF(air)
|
||||
// one-by-one, and Initalize_Atmos only ever adds `src` back in.
|
||||
active_turfs.Cut()
|
||||
|
||||
for(var/thing in turfs_to_init)
|
||||
for(var/thing in ALL_TURFS())
|
||||
var/turf/T = thing
|
||||
if (T.blocks_air)
|
||||
continue
|
||||
|
||||
55
code/controllers/subsystem/area_contents.dm
Normal file
55
code/controllers/subsystem/area_contents.dm
Normal file
@@ -0,0 +1,55 @@
|
||||
#define ALLOWED_LOOSE_TURFS 500
|
||||
/**
|
||||
* Responsible for managing the sizes of area.contained_turfs and area.turfs_to_uncontain
|
||||
* These lists do not check for duplicates, which is fine, but it also means they can balloon in size over time
|
||||
* as a consequence of repeated changes in area in a space
|
||||
* They additionally may not always resolve often enough to avoid memory leaks
|
||||
* This is annoying, so lets keep an eye on them and cut them down to size if needed
|
||||
*/
|
||||
SUBSYSTEM_DEF(area_contents)
|
||||
name = "Area Contents"
|
||||
flags = SS_NO_INIT
|
||||
runlevels = RUNLEVEL_LOBBY|RUNLEVELS_DEFAULT
|
||||
var/list/currentrun
|
||||
var/list/area/marked_for_clearing = list()
|
||||
|
||||
/datum/controller/subsystem/area_contents/stat_entry(msg)
|
||||
var/total_clearing_from = 0
|
||||
var/total_to_clear = 0
|
||||
for(var/area/to_clear as anything in marked_for_clearing)
|
||||
total_to_clear += length(to_clear.turfs_to_uncontain)
|
||||
total_clearing_from += length(to_clear.contained_turfs)
|
||||
msg = "A:[length(currentrun)] MR:[length(marked_for_clearing)] TC:[total_to_clear] CF:[total_clearing_from]"
|
||||
return ..()
|
||||
|
||||
|
||||
/datum/controller/subsystem/area_contents/fire(resumed)
|
||||
if(!resumed)
|
||||
currentrun = GLOB.areas.Copy()
|
||||
|
||||
while(length(currentrun))
|
||||
var/area/test = currentrun[length(currentrun)]
|
||||
if(length(test.turfs_to_uncontain) > ALLOWED_LOOSE_TURFS)
|
||||
marked_for_clearing |= test
|
||||
currentrun.len--
|
||||
if(MC_TICK_CHECK)
|
||||
return
|
||||
|
||||
// Alright, if we've done a scan on all our areas, it's time to knock the existing ones down to size
|
||||
while(length(marked_for_clearing))
|
||||
var/area/clear = marked_for_clearing[length(marked_for_clearing)]
|
||||
|
||||
// The operation of cutting large lists can be expensive
|
||||
// It scales almost directly with the size of the list we're cutting with
|
||||
// Because of this, we're gonna stick to cutting 1 entry at a time
|
||||
// There's no reason to batch it I promise, this is faster. No overtime too
|
||||
var/amount_cut = 0
|
||||
var/list/cut_from = clear.turfs_to_uncontain
|
||||
for(amount_cut in 1 to length(cut_from))
|
||||
clear.contained_turfs -= cut_from[amount_cut]
|
||||
if(MC_TICK_CHECK)
|
||||
cut_from.Cut(1, amount_cut + 1)
|
||||
return
|
||||
|
||||
clear.turfs_to_uncontain = list()
|
||||
marked_for_clearing.len--
|
||||
@@ -1,7 +1,7 @@
|
||||
SUBSYSTEM_DEF(mapping)
|
||||
name = "Mapping"
|
||||
init_order = INIT_ORDER_MAPPING
|
||||
flags = SS_NO_FIRE
|
||||
runlevels = ALL
|
||||
|
||||
loading_points = 11 SECONDS // Yogs -- loading times
|
||||
|
||||
@@ -32,6 +32,8 @@ SUBSYSTEM_DEF(mapping)
|
||||
var/list/turf/unused_turfs = list() //Not actually unused turfs they're unused but reserved for use for whatever requests them. "[zlevel_of_turf]" = list(turfs)
|
||||
var/list/datum/turf_reservations //list of turf reservations
|
||||
var/list/used_turfs = list() //list of turf = datum/turf_reservation
|
||||
/// List of lists of turfs to reserve
|
||||
var/list/lists_to_reserve = list()
|
||||
|
||||
var/clearing_reserved_turfs = FALSE
|
||||
|
||||
@@ -63,7 +65,7 @@ SUBSYSTEM_DEF(mapping)
|
||||
to_chat(world, span_boldannounce("Unable to load next or default map config, defaulting to Box Station"))
|
||||
config = old_config
|
||||
loadWorld()
|
||||
repopulate_sorted_areas()
|
||||
require_area_resort()
|
||||
process_teleport_locs() //Sets up the wizard teleport locations
|
||||
preloadTemplates()
|
||||
run_map_generation()
|
||||
@@ -91,20 +93,20 @@ SUBSYSTEM_DEF(mapping)
|
||||
loading_ruins = TRUE
|
||||
var/list/lava_ruins = levels_by_trait(ZTRAIT_LAVA_RUINS)
|
||||
if (lava_ruins.len)
|
||||
seedRuins(lava_ruins, CONFIG_GET(number/lavaland_budget), list(/area/lavaland/surface/outdoors/unexplored), lava_ruins_templates)
|
||||
seedRuins(lava_ruins, CONFIG_GET(number/lavaland_budget), list(/area/lavaland/surface/outdoors/unexplored), lava_ruins_templates, clear_below = TRUE)
|
||||
for (var/lava_z in lava_ruins)
|
||||
spawn_rivers(lava_z)
|
||||
|
||||
var/list/ice_ruins = levels_by_trait(ZTRAIT_ICE_RUINS)
|
||||
if (ice_ruins.len)
|
||||
// needs to be whitelisted for underground too so place_below ruins work
|
||||
seedRuins(ice_ruins, CONFIG_GET(number/icemoon_budget), list(/area/icemoon/surface/outdoors/unexplored, /area/icemoon/underground/unexplored), ice_ruins_templates)
|
||||
seedRuins(ice_ruins, CONFIG_GET(number/icemoon_budget), list(/area/icemoon/surface/outdoors/unexplored, /area/icemoon/underground/unexplored), ice_ruins_templates, clear_below = TRUE)
|
||||
for(var/ice_z in ice_ruins)
|
||||
spawn_rivers(ice_z, 4, /turf/open/openspace/icemoon, /area/icemoon/surface/outdoors/unexplored)
|
||||
|
||||
var/list/ice_ruins_underground = levels_by_trait(ZTRAIT_ICE_RUINS_UNDERGROUND)
|
||||
if (ice_ruins_underground.len)
|
||||
seedRuins(ice_ruins_underground, CONFIG_GET(number/icemoon_budget), list(/area/icemoon/underground/unexplored), ice_ruins_underground_templates)
|
||||
seedRuins(ice_ruins_underground, CONFIG_GET(number/icemoon_budget), list(/area/icemoon/underground/unexplored), ice_ruins_underground_templates, clear_below = TRUE)
|
||||
for(var/ice_z in ice_ruins_underground)
|
||||
spawn_rivers(ice_z, 4, /turf/open/lava/plasma/ice_moon, /area/icemoon/underground/unexplored)
|
||||
|
||||
@@ -134,7 +136,7 @@ SUBSYSTEM_DEF(mapping)
|
||||
PM.initTemplateBounds()
|
||||
// Add the transit level
|
||||
transit = add_new_zlevel("Transit/Reserved", list(ZTRAIT_RESERVED = TRUE))
|
||||
repopulate_sorted_areas()
|
||||
require_area_resort()
|
||||
// Set up Z-level transitions.
|
||||
setup_map_transitions()
|
||||
generate_station_area_list()
|
||||
@@ -143,6 +145,35 @@ SUBSYSTEM_DEF(mapping)
|
||||
build_minimaps()
|
||||
return SS_INIT_SUCCESS
|
||||
|
||||
/datum/controller/subsystem/mapping/fire(resumed)
|
||||
// Cache for sonic speed
|
||||
var/list/unused_turfs = src.unused_turfs
|
||||
var/list/world_contents = GLOB.areas_by_type[world.area].contents
|
||||
var/list/world_turf_contents = GLOB.areas_by_type[world.area].contained_turfs
|
||||
var/list/lists_to_reserve = src.lists_to_reserve
|
||||
var/index = 0
|
||||
while(index < length(lists_to_reserve))
|
||||
var/list/packet = lists_to_reserve[index + 1]
|
||||
var/packetlen = length(packet)
|
||||
while(packetlen)
|
||||
if(MC_TICK_CHECK)
|
||||
lists_to_reserve.Cut(1, index)
|
||||
return
|
||||
var/turf/T = packet[packetlen]
|
||||
T.empty(RESERVED_TURF_TYPE, RESERVED_TURF_TYPE, null, TRUE)
|
||||
LAZYINITLIST(unused_turfs["[T.z]"])
|
||||
unused_turfs["[T.z]"] |= T
|
||||
var/area/old_area = T.loc
|
||||
old_area.turfs_to_uncontain += T
|
||||
T.flags_1 |= UNUSED_RESERVATION_TURF_1
|
||||
world_contents += T
|
||||
world_turf_contents += T
|
||||
packet.len--
|
||||
packetlen = length(packet)
|
||||
|
||||
index++
|
||||
lists_to_reserve.Cut(1, index)
|
||||
|
||||
/datum/controller/subsystem/mapping/proc/wipe_reservations(wipe_safety_delay = 100)
|
||||
if(clearing_reserved_turfs || !initialized) //in either case this is just not needed.
|
||||
return
|
||||
@@ -250,13 +281,13 @@ SUBSYSTEM_DEF(mapping)
|
||||
var/start_z = world.maxz + 1
|
||||
var/i = 0
|
||||
for (var/level in traits)
|
||||
add_new_zlevel("[name][i ? " [i + 1]" : ""]", level)
|
||||
add_new_zlevel("[name][i ? " [i + 1]" : ""]", level, contain_turfs = FALSE)
|
||||
++i
|
||||
|
||||
// load the maps
|
||||
for (var/P in parsed_maps)
|
||||
var/datum/parsed_map/pm = P
|
||||
if (!pm.load(1, 1, start_z + parsed_maps[P], no_changeturf = TRUE))
|
||||
if (!pm.load(1, 1, start_z + parsed_maps[P], no_changeturf = TRUE, new_z = TRUE))
|
||||
errorList |= pm.original_path
|
||||
if(!silent)
|
||||
INIT_ANNOUNCE("Loaded [name] in [(REALTIMEOFDAY - start_time)/10]s!")
|
||||
@@ -310,7 +341,7 @@ GLOBAL_LIST_EMPTY(the_station_areas)
|
||||
|
||||
/datum/controller/subsystem/mapping/proc/generate_station_area_list()
|
||||
var/list/station_areas_blacklist = typecacheof(list(/area/space, /area/mine, /area/ruin, /area/asteroid/nearstation))
|
||||
for(var/area/A in world)
|
||||
for(var/area/A in GLOB.areas)
|
||||
if (is_type_in_typecache(A, station_areas_blacklist))
|
||||
continue
|
||||
if (!A.contents.len || !A.unique)
|
||||
@@ -323,7 +354,7 @@ GLOBAL_LIST_EMPTY(the_station_areas)
|
||||
log_world("ERROR: Station areas list failed to generate!")
|
||||
|
||||
/datum/controller/subsystem/mapping/proc/run_map_generation()
|
||||
for(var/area/A in world)
|
||||
for(var/area/A as anything in GLOB.areas)
|
||||
A.RunGeneration()
|
||||
|
||||
/datum/controller/subsystem/mapping/proc/maprotate()
|
||||
@@ -549,15 +580,12 @@ GLOBAL_LIST_EMPTY(the_station_areas)
|
||||
unused_turfs["[i]"] = block
|
||||
clearing_reserved_turfs = FALSE
|
||||
|
||||
/datum/controller/subsystem/mapping/proc/reserve_turfs(list/turfs)
|
||||
for(var/i in turfs)
|
||||
var/turf/T = i
|
||||
T.empty(RESERVED_TURF_TYPE, RESERVED_TURF_TYPE, null, TRUE)
|
||||
LAZYINITLIST(unused_turfs["[T.z]"])
|
||||
unused_turfs["[T.z]"] |= T
|
||||
T.flags_1 |= UNUSED_RESERVATION_TURF_1
|
||||
GLOB.areas_by_type[world.area].contents += T
|
||||
CHECK_TICK
|
||||
/// Schedules a group of turfs to be handed back to the reservation system's control
|
||||
/// If await is true, will sleep until the turfs are finished work
|
||||
/datum/controller/subsystem/mapping/proc/reserve_turfs(list/turfs, await = FALSE)
|
||||
lists_to_reserve += list(turfs)
|
||||
if(await)
|
||||
UNTIL(!length(turfs))
|
||||
|
||||
//DO NOT CALL THIS PROC DIRECTLY, CALL wipe_reservations().
|
||||
/datum/controller/subsystem/mapping/proc/do_wipe_turf_reservations()
|
||||
@@ -575,7 +603,7 @@ GLOBAL_LIST_EMPTY(the_station_areas)
|
||||
clearing |= used_turfs //used turfs is an associative list, BUT, reserve_turfs() can still handle it. If the code above works properly, this won't even be needed as the turfs would be freed already.
|
||||
unused_turfs.Cut()
|
||||
used_turfs.Cut()
|
||||
reserve_turfs(clearing)
|
||||
reserve_turfs(clearing, await = TRUE)
|
||||
|
||||
/datum/controller/subsystem/mapping/proc/build_minimaps()
|
||||
to_chat(world, span_boldannounce("Building minimaps..."))
|
||||
@@ -586,3 +614,15 @@ GLOBAL_LIST_EMPTY(the_station_areas)
|
||||
for(var/B in areas)
|
||||
var/area/A = B
|
||||
A.reg_in_areas_in_z()
|
||||
|
||||
/datum/controller/subsystem/mapping/proc/build_area_turfs(z_level, space_guaranteed)
|
||||
// If we know this is filled with default tiles, we can use the default area
|
||||
// Faster
|
||||
if(space_guaranteed)
|
||||
var/area/global_area = GLOB.areas_by_type[world.area]
|
||||
global_area.contained_turfs += Z_TURFS(z_level)
|
||||
return
|
||||
|
||||
for(var/turf/to_contain as anything in Z_TURFS(z_level))
|
||||
var/area/our_area = to_contain.loc
|
||||
our_area.contained_turfs += to_contain
|
||||
|
||||
@@ -516,9 +516,12 @@ SUBSYSTEM_DEF(shuttle)
|
||||
var/turf/midpoint = locate(transit_x, transit_y, bottomleft.z)
|
||||
if(!midpoint)
|
||||
return FALSE
|
||||
var/area/old_area = midpoint.loc
|
||||
old_area.turfs_to_uncontain += proposal.reserved_turfs
|
||||
var/area/shuttle/transit/A = new()
|
||||
A.parallax_movedir = travel_dir
|
||||
A.contents = proposal.reserved_turfs
|
||||
A.contained_turfs = proposal.reserved_turfs
|
||||
var/obj/docking_port/stationary/transit/new_transit_dock = new(midpoint)
|
||||
new_transit_dock.reserved_area = proposal
|
||||
new_transit_dock.name = "Transit for [M.id]/[M.name]"
|
||||
|
||||
@@ -1,19 +1,33 @@
|
||||
/datum/map_generator/cave_generator
|
||||
var/name = "Cave Generator"
|
||||
///Weighted list of the types that spawns if the turf is open
|
||||
var/open_turf_types = list(/turf/open/floor/plating/asteroid/airless = 1)
|
||||
var/weighted_open_turf_types = list(/turf/open/floor/plating/asteroid/airless = 1)
|
||||
///Expanded list of the types that spawns if the turf is open
|
||||
var/open_turf_types
|
||||
///Weighted list of the types that spawns if the turf is closed
|
||||
var/closed_turf_types = list(/turf/closed/mineral/random = 1)
|
||||
var/weighted_closed_turf_types = list(/turf/closed/mineral/random = 1)
|
||||
///Expanded list of the types that spawns if the turf is closed
|
||||
var/closed_turf_types
|
||||
///If this is set to TRUE then it will only change turfs that are /turf/open/genturf, for more flexability in design
|
||||
var/gen_gurf_only = TRUE
|
||||
|
||||
///Weighted list of mobs that can spawn in the area.
|
||||
var/list/weighted_mob_spawn_list
|
||||
///Expanded list of mobs that can spawn in the area. Reads from the weighted list
|
||||
var/list/mob_spawn_list
|
||||
// Weighted list of Megafauna that can spawn in the caves
|
||||
///The mob spawn list but with no megafauna markers. autogenerated
|
||||
var/list/mob_spawn_no_mega_list
|
||||
// Weighted list of Megafauna that can spawn in the area
|
||||
var/list/weighted_megafauna_spawn_list
|
||||
///Expanded list of Megafauna that can spawn in the area. Reads from the weighted list
|
||||
var/list/megafauna_spawn_list
|
||||
///Weighted list of flora that can spawn in the area.
|
||||
var/list/weighted_flora_spawn_list
|
||||
///Expanded list of flora that can spawn in the area. Reads from the weighted list
|
||||
var/list/flora_spawn_list
|
||||
///Weighted list of extra features that can spawn in the area, such as geysers.
|
||||
var/list/weighted_feature_spawn_list
|
||||
///Expanded list of extra features that can spawn in the area. Reads from the weighted list
|
||||
var/list/feature_spawn_list
|
||||
|
||||
|
||||
@@ -37,113 +51,119 @@
|
||||
|
||||
/datum/map_generator/cave_generator/New()
|
||||
. = ..()
|
||||
if(!mob_spawn_list)
|
||||
mob_spawn_list = list(/mob/living/simple_animal/hostile/asteroid/goldgrub = 1, /mob/living/simple_animal/hostile/asteroid/goliath = 5, /mob/living/simple_animal/hostile/asteroid/basilisk = 4, /mob/living/simple_animal/hostile/asteroid/hivelord = 3)
|
||||
if(!megafauna_spawn_list)
|
||||
megafauna_spawn_list = GLOB.megafauna_spawn_list
|
||||
if(!flora_spawn_list)
|
||||
flora_spawn_list = list(/obj/structure/flora/ash/leaf_shroom = 2 , /obj/structure/flora/ash/cap_shroom = 2 , /obj/structure/flora/ash/stem_shroom = 2 , /obj/structure/flora/ash/cacti = 1, /obj/structure/flora/ash/tall_shroom = 2)
|
||||
if(!feature_spawn_list)
|
||||
feature_spawn_list = list() //yogs no geysers in asteroid caves
|
||||
if(!weighted_mob_spawn_list)
|
||||
weighted_mob_spawn_list = list(/mob/living/simple_animal/hostile/asteroid/goldgrub = 1, /mob/living/simple_animal/hostile/asteroid/goliath = 5, /mob/living/simple_animal/hostile/asteroid/basilisk = 4, /mob/living/simple_animal/hostile/asteroid/hivelord = 3)
|
||||
mob_spawn_list = expand_weights(weighted_mob_spawn_list)
|
||||
mob_spawn_no_mega_list = expand_weights(weighted_mob_spawn_list - SPAWN_MEGAFAUNA)
|
||||
if(!weighted_megafauna_spawn_list)
|
||||
weighted_megafauna_spawn_list = GLOB.megafauna_spawn_list
|
||||
megafauna_spawn_list = expand_weights(weighted_megafauna_spawn_list)
|
||||
if(!weighted_flora_spawn_list)
|
||||
weighted_flora_spawn_list = list(/obj/structure/flora/ash/leaf_shroom = 2 , /obj/structure/flora/ash/cap_shroom = 2 , /obj/structure/flora/ash/stem_shroom = 2 , /obj/structure/flora/ash/cacti = 1, /obj/structure/flora/ash/tall_shroom = 2, /obj/structure/flora/ash/seraka = 2)
|
||||
flora_spawn_list = expand_weights(weighted_flora_spawn_list)
|
||||
if(!weighted_feature_spawn_list)
|
||||
weighted_feature_spawn_list = list() // yogs - no geysers in asteroid caves
|
||||
feature_spawn_list = expand_weights(weighted_feature_spawn_list)
|
||||
open_turf_types = expand_weights(weighted_open_turf_types)
|
||||
closed_turf_types = expand_weights(weighted_closed_turf_types)
|
||||
|
||||
/datum/map_generator/cave_generator/generate_terrain(list/turfs)
|
||||
/datum/map_generator/cave_generator/generate_terrain(list/turfs, area/generate_in)
|
||||
. = ..()
|
||||
if(!(generate_in.area_flags & CAVES_ALLOWED))
|
||||
return
|
||||
|
||||
var/start_time = REALTIMEOFDAY
|
||||
string_gen = rustg_cnoise_generate("[initial_closed_chance]", "[smoothing_iterations]", "[birth_limit]", "[death_limit]", "[world.maxx]", "[world.maxy]") //Generate the raw CA data
|
||||
|
||||
// Area var pullouts to make accessing in the loop faster
|
||||
var/flora_allowed = (generate_in.area_flags & FLORA_ALLOWED) && length(flora_spawn_list)
|
||||
var/feature_allowed = (generate_in.area_flags & FLORA_ALLOWED) && length(feature_spawn_list)
|
||||
var/mobs_allowed = (generate_in.area_flags & MOB_SPAWN_ALLOWED) && length(mob_spawn_list)
|
||||
var/megas_allowed = (generate_in.area_flags & MEGAFAUNA_SPAWN_ALLOWED) && length(megafauna_spawn_list)
|
||||
|
||||
for(var/i in turfs) //Go through all the turfs and generate them
|
||||
var/turf/gen_turf = i
|
||||
|
||||
if(gen_gurf_only && !istype(gen_turf,/turf/open/genturf))
|
||||
if(gen_gurf_only && !istype(gen_turf, /turf/open/genturf))
|
||||
continue
|
||||
|
||||
if(istype(gen_turf,/turf/closed/mineral))
|
||||
if(istype(gen_turf, /turf/closed/mineral))
|
||||
continue
|
||||
|
||||
var/area/A = gen_turf.loc
|
||||
if(!(A.area_flags & CAVES_ALLOWED))
|
||||
continue
|
||||
var/closed = string_gen[world.maxx * (gen_turf.y - 1) + gen_turf.x] != "0"
|
||||
var/turf/new_turf = pick(closed ? closed_turf_types : open_turf_types)
|
||||
|
||||
var/closed = text2num(string_gen[world.maxx * (gen_turf.y - 1) + gen_turf.x])
|
||||
// The assumption is this will be faster then changeturf, and changeturf isn't required since by this point
|
||||
// The old tile hasn't got the chance to init yet
|
||||
new_turf = new new_turf(gen_turf)
|
||||
|
||||
var/stored_flags
|
||||
if(gen_turf.flags_1 & NO_RUINS_1)
|
||||
stored_flags |= NO_RUINS_1
|
||||
new_turf.flags_1 |= NO_RUINS_1
|
||||
|
||||
var/turf/new_turf = pickweight(closed ? closed_turf_types : open_turf_types)
|
||||
if(closed) //Open turfs have some special behavior related to spawning flora and mobs.
|
||||
CHECK_TICK
|
||||
continue
|
||||
|
||||
new_turf = gen_turf.ChangeTurf(new_turf, initial(new_turf.baseturfs), CHANGETURF_DEFER_CHANGE)
|
||||
// If we've spawned something yet
|
||||
var/spawned_something = FALSE
|
||||
|
||||
new_turf.flags_1 |= stored_flags
|
||||
///Spawning isn't done in procs to save on overhead on the 60k turfs we're going through.
|
||||
//FLORA SPAWNING HERE
|
||||
if(flora_allowed && prob(flora_spawn_chance))
|
||||
var/flora_type = pick(flora_spawn_list)
|
||||
new flora_type(new_turf)
|
||||
spawned_something = TRUE
|
||||
|
||||
if(!closed)//Open turfs have some special behavior related to spawning flora and mobs.
|
||||
//FEATURE SPAWNING HERE
|
||||
if(feature_allowed && prob(feature_spawn_chance))
|
||||
var/can_spawn = TRUE
|
||||
|
||||
var/turf/open/new_open_turf = new_turf
|
||||
var/atom/picked_feature = pick(feature_spawn_list)
|
||||
|
||||
///Spawning isn't done in procs to save on overhead on the 60k turfs we're going through.
|
||||
|
||||
//FLORA SPAWNING HERE
|
||||
var/atom/spawned_flora
|
||||
if(flora_spawn_list && !isemptylist(flora_spawn_list) && prob(flora_spawn_chance))
|
||||
var/can_spawn = TRUE
|
||||
|
||||
if(!(A.area_flags & FLORA_ALLOWED))
|
||||
for(var/obj/structure/existing_feature in range(7, new_turf))
|
||||
if(istype(existing_feature, picked_feature))
|
||||
can_spawn = FALSE
|
||||
if(can_spawn)
|
||||
spawned_flora = pickweight(flora_spawn_list)
|
||||
spawned_flora = new spawned_flora(new_open_turf)
|
||||
break
|
||||
|
||||
if(can_spawn)
|
||||
new picked_feature(new_turf)
|
||||
spawned_something = TRUE
|
||||
|
||||
//FEATURE SPAWNING HERE
|
||||
var/atom/spawned_feature
|
||||
if(feature_spawn_list && !isemptylist(feature_spawn_list) && prob(feature_spawn_chance))
|
||||
var/can_spawn = TRUE
|
||||
//MOB SPAWNING HERE
|
||||
if(mobs_allowed && !spawned_something && prob(mob_spawn_chance))
|
||||
var/atom/picked_mob = pick(mob_spawn_list)
|
||||
|
||||
if(!(A.area_flags & FLORA_ALLOWED)) //checks the same flag because lol dunno
|
||||
if(picked_mob == SPAWN_MEGAFAUNA)
|
||||
if(megas_allowed) //this is danger. it's boss time.
|
||||
picked_mob = pick(megafauna_spawn_list)
|
||||
else //this is not danger, don't spawn a boss, spawn something else
|
||||
picked_mob = pick(mob_spawn_no_mega_list) //What if we used 100% of the brain...and did something (slightly) less shit than a while loop?
|
||||
|
||||
var/can_spawn = TRUE
|
||||
|
||||
// prevents tendrils spawning in each other's collapse range
|
||||
if(ispath(picked_mob, /obj/structure/spawner/lavaland))
|
||||
for(var/obj/structure/spawner/lavaland/spawn_blocker in range(2, new_turf))
|
||||
can_spawn = FALSE
|
||||
|
||||
var/atom/picked_feature = pickweight(feature_spawn_list)
|
||||
|
||||
for(var/obj/structure/F in range(7, new_open_turf))
|
||||
if(istype(F, picked_feature))
|
||||
can_spawn = FALSE
|
||||
|
||||
if(can_spawn)
|
||||
spawned_feature = new picked_feature(new_open_turf)
|
||||
|
||||
//MOB SPAWNING HERE
|
||||
|
||||
if(mob_spawn_list && !isemptylist(mob_spawn_list) && !spawned_flora && !spawned_feature && prob(mob_spawn_chance))
|
||||
var/can_spawn = TRUE
|
||||
|
||||
if(!(A.area_flags & MOB_SPAWN_ALLOWED))
|
||||
break
|
||||
//if the random is a standard mob, avoid spawning if there's another one within 12 tiles
|
||||
else if(ispath(picked_mob, /mob/living/simple_animal/hostile/asteroid))
|
||||
for(var/mob/living/simple_animal/hostile/asteroid/mob_blocker in range(12, new_turf))
|
||||
can_spawn = FALSE
|
||||
break
|
||||
//if there's a megafauna within standard view don't spawn anything at all (This isn't really consistent, I don't know why we do this. you do you tho)
|
||||
if(can_spawn)
|
||||
for(var/mob/living/simple_animal/hostile/megafauna/found_fauna in range(7, new_turf))
|
||||
can_spawn = FALSE
|
||||
break
|
||||
|
||||
var/atom/picked_mob = pickweight(mob_spawn_list)
|
||||
|
||||
if(picked_mob == SPAWN_MEGAFAUNA) //
|
||||
if((A.area_flags & MEGAFAUNA_SPAWN_ALLOWED) && megafauna_spawn_list?.len) //this is danger. it's boss time.
|
||||
picked_mob = pickweight(megafauna_spawn_list)
|
||||
else //this is not danger, don't spawn a boss, spawn something else
|
||||
picked_mob = pickweight(mob_spawn_list - SPAWN_MEGAFAUNA) //What if we used 100% of the brain...and did something (slightly) less shit than a while loop?
|
||||
|
||||
for(var/thing in urange(12, new_open_turf)) //prevents mob clumps
|
||||
if(!ishostile(thing) && !istype(thing, /obj/structure/spawner))
|
||||
continue
|
||||
if((ispath(picked_mob, /mob/living/simple_animal/hostile/megafauna) || ismegafauna(thing)) && get_dist(new_open_turf, thing) <= 7)
|
||||
can_spawn = FALSE //if there's a megafauna within standard view don't spawn anything at all
|
||||
break
|
||||
if(ispath(picked_mob, /mob/living/simple_animal/hostile/asteroid) || istype(thing, /mob/living/simple_animal/hostile/asteroid))
|
||||
can_spawn = FALSE //if the random is a standard mob, avoid spawning if there's another one within 12 tiles
|
||||
break
|
||||
if((ispath(picked_mob, /obj/structure/spawner/lavaland) || istype(thing, /obj/structure/spawner/lavaland)) && get_dist(new_open_turf, thing) <= 2)
|
||||
can_spawn = FALSE //prevents tendrils spawning in each other's collapse range
|
||||
break
|
||||
|
||||
if(can_spawn)
|
||||
if(ispath(picked_mob, /mob/living/simple_animal/hostile/megafauna/bubblegum)) //there can be only one bubblegum, so don't waste spawns on it
|
||||
megafauna_spawn_list.Remove(picked_mob)
|
||||
|
||||
new picked_mob(new_open_turf)
|
||||
if(can_spawn)
|
||||
if(ispath(picked_mob, /mob/living/simple_animal/hostile/megafauna/bubblegum)) //there can be only one bubblegum, so don't waste spawns on it
|
||||
weighted_megafauna_spawn_list.Remove(picked_mob)
|
||||
megafauna_spawn_list = expand_weights(weighted_megafauna_spawn_list)
|
||||
megas_allowed = megas_allowed && length(megafauna_spawn_list)
|
||||
new picked_mob(new_turf)
|
||||
spawned_something = TRUE
|
||||
CHECK_TICK
|
||||
|
||||
var/message = "[name] finished in [(REALTIMEOFDAY - start_time)/10]s!"
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
/datum/map_generator/cave_generator/icemoon
|
||||
open_turf_types = list(/turf/open/floor/plating/asteroid/snow/icemoon = 19, /turf/open/floor/plating/ice/icemoon = 1)
|
||||
closed_turf_types = list(/turf/closed/mineral/random/snow = 1)
|
||||
weighted_open_turf_types = list(/turf/open/floor/plating/asteroid/snow/icemoon = 19, /turf/open/floor/plating/ice/icemoon = 1)
|
||||
weighted_closed_turf_types = list(/turf/closed/mineral/random/snow = 1)
|
||||
|
||||
|
||||
mob_spawn_list = list(/mob/living/simple_animal/hostile/asteroid/wolf = 50, /obj/structure/spawner/ice_moon = 3, \
|
||||
weighted_mob_spawn_list = list(/mob/living/simple_animal/hostile/asteroid/wolf = 50, /obj/structure/spawner/ice_moon = 3, \
|
||||
/mob/living/simple_animal/hostile/asteroid/polarbear = 30, /obj/structure/spawner/ice_moon/polarbear = 3, \
|
||||
/mob/living/simple_animal/hostile/asteroid/hivelord/legion/snow = 50,
|
||||
/mob/living/simple_animal/hostile/asteroid/marrowweaver/ice = 30,
|
||||
/mob/living/simple_animal/hostile/asteroid/goldgrub = 10)
|
||||
flora_spawn_list = list(/obj/structure/flora/tree/pine = 2, /obj/structure/flora/rock/icy = 2, /obj/structure/flora/rock/pile/icy = 2, /obj/structure/flora/grass/both = 6)
|
||||
weighted_flora_spawn_list = list(/obj/structure/flora/tree/pine = 2, /obj/structure/flora/rock/icy = 2, /obj/structure/flora/rock/pile/icy = 2, /obj/structure/flora/grass/both = 6)
|
||||
///Note that this spawn list is also in the lavaland generator
|
||||
feature_spawn_list = list()
|
||||
weighted_feature_spawn_list = null
|
||||
|
||||
/datum/map_generator/cave_generator/icemoon/surface
|
||||
flora_spawn_chance = 4
|
||||
mob_spawn_list = list(/mob/living/simple_animal/hostile/asteroid/wolf = 50, /obj/structure/spawner/ice_moon = 3, \
|
||||
weighted_mob_spawn_list = list(/mob/living/simple_animal/hostile/asteroid/wolf = 50, /obj/structure/spawner/ice_moon = 3, \
|
||||
/mob/living/simple_animal/hostile/asteroid/polarbear = 30, /obj/structure/spawner/ice_moon/polarbear = 3, \
|
||||
/mob/living/simple_animal/hostile/asteroid/hivelord/legion/snow = 50,
|
||||
/mob/living/simple_animal/hostile/asteroid/marrowweaver/ice = 30,
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
/datum/map_generator/cave_generator/lavaland
|
||||
name = "Lavaland Base"
|
||||
open_turf_types = list(/turf/open/floor/plating/asteroid/basalt/lava_land_surface = 1)
|
||||
closed_turf_types = list(/turf/closed/mineral/random/volcanic = 1)
|
||||
weighted_open_turf_types = list(/turf/open/floor/plating/asteroid/basalt/lava_land_surface = 1)
|
||||
weighted_closed_turf_types = list(/turf/closed/mineral/random/volcanic = 1)
|
||||
|
||||
|
||||
mob_spawn_list = list(/mob/living/simple_animal/hostile/asteroid/goliath/beast/random = 50, /obj/structure/spawner/lavaland/goliath = 3, \
|
||||
weighted_mob_spawn_list = list(/mob/living/simple_animal/hostile/asteroid/goliath/beast/random = 50, /obj/structure/spawner/lavaland/goliath = 3, \
|
||||
/mob/living/simple_animal/hostile/asteroid/basilisk/watcher/random = 40, /obj/structure/spawner/lavaland = 2, \
|
||||
/mob/living/simple_animal/hostile/asteroid/hivelord/legion/random = 30, /obj/structure/spawner/lavaland/legion = 3, \
|
||||
/mob/living/simple_animal/hostile/asteroid/marrowweaver = 30,
|
||||
SPAWN_MEGAFAUNA = 4, /mob/living/simple_animal/hostile/asteroid/goldgrub = 10
|
||||
)
|
||||
flora_spawn_list = list(/obj/structure/flora/ash/leaf_shroom = 2 , /obj/structure/flora/ash/cap_shroom = 2 , /obj/structure/flora/ash/stem_shroom = 2 , /obj/structure/flora/ash/cacti = 1, /obj/structure/flora/ash/tall_shroom = 2)
|
||||
weighted_flora_spawn_list = list(/obj/structure/flora/ash/leaf_shroom = 2 , /obj/structure/flora/ash/cap_shroom = 2 , /obj/structure/flora/ash/stem_shroom = 2 , /obj/structure/flora/ash/cacti = 1, /obj/structure/flora/ash/tall_shroom = 2)
|
||||
///Note that this spawn list is also in the icemoon generator
|
||||
feature_spawn_list = list(/obj/structure/geyser/ash = 10, /obj/structure/geyser/random = 2, /obj/structure/geyser/stable_plasma = 6, /obj/structure/geyser/oil = 8,/obj/structure/geyser/protozine = 10,/obj/structure/geyser/holywater = 2) //yogs, yes geysers
|
||||
weighted_feature_spawn_list = list(/obj/structure/geyser/ash = 10, /obj/structure/geyser/random = 2, /obj/structure/geyser/stable_plasma = 6, /obj/structure/geyser/oil = 8,/obj/structure/geyser/protozine = 10,/obj/structure/geyser/holywater = 2) //yogs, yes geysers
|
||||
|
||||
initial_closed_chance = 45
|
||||
smoothing_iterations = 50
|
||||
@@ -37,7 +37,7 @@
|
||||
var/min_offset = 0
|
||||
var/max_offset = 5
|
||||
|
||||
/datum/map_generator/cave_generator/lavaland/generate_terrain(list/turfs)
|
||||
/datum/map_generator/cave_generator/lavaland/generate_terrain(list/turfs, area/generate_in)
|
||||
. = ..()
|
||||
var/start_time = REALTIMEOFDAY
|
||||
var/node_amount = rand(6,10)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
/datum/map_generator
|
||||
|
||||
///This proc will be ran by areas on Initialize, and provides the areas turfs as argument to allow for generation.
|
||||
/datum/map_generator/proc/generate_terrain(list/turfs)
|
||||
/datum/map_generator/proc/generate_terrain(list/turfs, area/generate_in)
|
||||
return
|
||||
|
||||
/turf/open/genturf
|
||||
|
||||
@@ -14,6 +14,15 @@
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
invisibility = INVISIBILITY_LIGHTING
|
||||
|
||||
/// List of all turfs currently inside this area. Acts as a filtered bersion of area.contents
|
||||
/// For faster lookup (area.contents is actually a filtered loop over world)
|
||||
/// Semi fragile, but it prevents stupid so I think it's worth it
|
||||
var/list/turf/contained_turfs = list()
|
||||
/// Contained turfs is a MASSIVE list, so rather then adding/removing from it each time we have a problem turf
|
||||
/// We should instead store a list of turfs to REMOVE from it, then hook into a getter for it
|
||||
/// There is a risk of this and contained_turfs leaking, so a subsystem will run it down to 0 incrementally if it gets too large
|
||||
var/list/turf/turfs_to_uncontain = list()
|
||||
|
||||
var/area_flags = 0
|
||||
|
||||
var/map_name // Set in New(); preserves the name set by the map maker, even if renamed by the Blueprints.
|
||||
@@ -109,20 +118,16 @@ GLOBAL_LIST_EMPTY(teleportlocs)
|
||||
* The returned list of turfs is sorted by name
|
||||
*/
|
||||
/proc/process_teleport_locs()
|
||||
for(var/V in GLOB.sortedAreas)
|
||||
var/area/AR = V
|
||||
for(var/area/AR as anything in get_sorted_areas())
|
||||
if(istype(AR, /area/shuttle) || AR.noteleport)
|
||||
continue
|
||||
if(GLOB.teleportlocs[AR.name])
|
||||
continue
|
||||
if (!AR.contents.len)
|
||||
if (!AR.has_contained_turfs())
|
||||
continue
|
||||
var/turf/picked = AR.contents[1]
|
||||
if (picked && is_station_level(picked.z))
|
||||
if (is_station_level(AR.z))
|
||||
GLOB.teleportlocs[AR.name] = AR
|
||||
|
||||
sortTim(GLOB.teleportlocs, /proc/cmp_text_dsc)
|
||||
|
||||
/**
|
||||
* Called when an area loads
|
||||
*
|
||||
@@ -142,6 +147,7 @@ GLOBAL_LIST_EMPTY(teleportlocs)
|
||||
// rather than waiting for atoms to initialize.
|
||||
if (unique)
|
||||
GLOB.areas_by_type[type] = src
|
||||
GLOB.areas += src
|
||||
return ..()
|
||||
|
||||
/**
|
||||
@@ -197,14 +203,33 @@ GLOBAL_LIST_EMPTY(teleportlocs)
|
||||
var/list/turfs = list()
|
||||
for(var/turf/T in contents)
|
||||
turfs += T
|
||||
map_generator.generate_terrain(turfs)
|
||||
map_generator.generate_terrain(turfs, src)
|
||||
|
||||
/area/proc/test_gen()
|
||||
if(map_generator)
|
||||
var/list/turfs = list()
|
||||
for(var/turf/T in contents)
|
||||
turfs += T
|
||||
map_generator.generate_terrain(turfs)
|
||||
map_generator.generate_terrain(turfs, src)
|
||||
|
||||
/area/proc/get_contained_turfs()
|
||||
if(length(turfs_to_uncontain))
|
||||
cannonize_contained_turfs()
|
||||
return contained_turfs
|
||||
|
||||
/// Ensures that the contained_turfs list properly represents the turfs actually inside us
|
||||
/area/proc/cannonize_contained_turfs()
|
||||
// This is massively suboptimal for LARGE removal lists
|
||||
// Try and keep the mass removal as low as you can. We'll do this by ensuring
|
||||
// We only actually add to contained turfs after large changes (Also the management subsystem)
|
||||
// Do your damndest to keep turfs out of /area/space as a stepping stone
|
||||
// That sucker gets HUGE and will make this take actual tens of seconds if you stuff turfs_to_uncontain
|
||||
contained_turfs -= turfs_to_uncontain
|
||||
turfs_to_uncontain = list()
|
||||
|
||||
/// Returns TRUE if we have contained turfs, FALSE otherwise
|
||||
/area/proc/has_contained_turfs()
|
||||
return length(contained_turfs) - length(turfs_to_uncontain) > 0
|
||||
|
||||
/**
|
||||
* Register this area as belonging to a z level
|
||||
@@ -216,22 +241,16 @@ GLOBAL_LIST_EMPTY(teleportlocs)
|
||||
* areas don't have a valid z themself or something
|
||||
*/
|
||||
/area/proc/reg_in_areas_in_z()
|
||||
if(contents.len)
|
||||
var/list/areas_in_z = SSmapping.areas_in_z
|
||||
var/z
|
||||
update_areasize()
|
||||
for(var/i in 1 to contents.len)
|
||||
var/atom/thing = contents[i]
|
||||
if(!thing)
|
||||
continue
|
||||
z = thing.z
|
||||
break
|
||||
if(!z)
|
||||
WARNING("No z found for [src]")
|
||||
return
|
||||
if(!areas_in_z["[z]"])
|
||||
areas_in_z["[z]"] = list()
|
||||
areas_in_z["[z]"] += src
|
||||
if(!has_contained_turfs())
|
||||
return
|
||||
var/list/areas_in_z = SSmapping.areas_in_z
|
||||
update_areasize()
|
||||
if(!z)
|
||||
WARNING("No z found for [src]")
|
||||
return
|
||||
if(!areas_in_z["[z]"])
|
||||
areas_in_z["[z]"] = list()
|
||||
areas_in_z["[z]"] += src
|
||||
|
||||
/**
|
||||
* Destroy an area and clean it up
|
||||
@@ -244,6 +263,7 @@ GLOBAL_LIST_EMPTY(teleportlocs)
|
||||
/area/Destroy()
|
||||
if(GLOB.areas_by_type[type] == src)
|
||||
GLOB.areas_by_type[type] = null
|
||||
GLOB.areas -= src
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
return ..()
|
||||
|
||||
@@ -734,7 +754,7 @@ GLOBAL_LIST_EMPTY(teleportlocs)
|
||||
always_unpowered = FALSE
|
||||
valid_territory = FALSE
|
||||
blob_allowed = FALSE
|
||||
addSorted()
|
||||
require_area_resort()
|
||||
/**
|
||||
* Set the area size of the area
|
||||
*
|
||||
@@ -745,7 +765,7 @@ GLOBAL_LIST_EMPTY(teleportlocs)
|
||||
if(outdoors)
|
||||
return FALSE
|
||||
areasize = 0
|
||||
for(var/turf/open/T in contents)
|
||||
for(var/turf/open/T in get_contained_turfs())
|
||||
areasize++
|
||||
|
||||
/**
|
||||
|
||||
@@ -94,7 +94,7 @@
|
||||
*/
|
||||
/atom/New(loc, ...)
|
||||
//atom creation method that preloads variables at creation
|
||||
if(GLOB.use_preloader && (src.type == GLOB._preloader.target_path))//in case the instanciated atom is creating other atoms in New()
|
||||
if(GLOB.use_preloader && (src.type == GLOB._preloader_path))//in case the instanciated atom is creating other atoms in New()
|
||||
world.preloader_load(src)
|
||||
|
||||
if(datum_flags & DF_USE_TAG)
|
||||
|
||||
@@ -1480,7 +1480,7 @@ GLOBAL_LIST_EMPTY(possible_items_special)
|
||||
/datum/objective/contract/proc/generate_dropoff()
|
||||
var/found = FALSE
|
||||
while (!found)
|
||||
var/area/dropoff_area = pick(GLOB.sortedAreas)
|
||||
var/area/dropoff_area = pick(GLOB.areas)
|
||||
if(dropoff_area && is_station_level(dropoff_area.z) && !dropoff_area.outdoors)
|
||||
dropoff = dropoff_area
|
||||
found = TRUE
|
||||
|
||||
@@ -22,22 +22,23 @@
|
||||
var/obj/effect/landmark/river_waypoint/W = A
|
||||
if (W.z != target_z || W.connected)
|
||||
continue
|
||||
W.connected = 1
|
||||
W.connected = TRUE
|
||||
// Workaround around ChangeTurf that's safe because of when this proc is called
|
||||
var/turf/cur_turf = get_turf(W)
|
||||
cur_turf.ChangeTurf(turf_type, null, CHANGETURF_IGNORE_AIR)
|
||||
cur_turf = new turf_type(cur_turf)
|
||||
var/turf/target_turf = get_turf(pick(river_nodes - W))
|
||||
if(!target_turf)
|
||||
break
|
||||
var/detouring = 0
|
||||
var/detouring = FALSE
|
||||
var/cur_dir = get_dir(cur_turf, target_turf)
|
||||
while(cur_turf != target_turf)
|
||||
|
||||
if(detouring) //randomly snake around a bit
|
||||
if(prob(20))
|
||||
detouring = 0
|
||||
detouring = FALSE
|
||||
cur_dir = get_dir(cur_turf, target_turf)
|
||||
else if(prob(20))
|
||||
detouring = 1
|
||||
detouring = TRUE
|
||||
if(prob(50))
|
||||
cur_dir = turn(cur_dir, 45)
|
||||
else
|
||||
@@ -48,12 +49,13 @@
|
||||
cur_turf = get_step(cur_turf, cur_dir)
|
||||
var/area/new_area = get_area(cur_turf)
|
||||
if(!istype(new_area, whitelist_area) || (cur_turf.flags_1 & NO_LAVA_GEN_1)) //Rivers will skip ruins
|
||||
detouring = 0
|
||||
detouring = FALSE
|
||||
cur_dir = get_dir(cur_turf, target_turf)
|
||||
cur_turf = get_step(cur_turf, cur_dir)
|
||||
continue
|
||||
else
|
||||
var/turf/river_turf = cur_turf.ChangeTurf(turf_type, null, CHANGETURF_IGNORE_AIR)
|
||||
// Workaround around ChangeTurf that's safe because of when this proc is called
|
||||
var/turf/river_turf = new turf_type(cur_turf)
|
||||
river_turf.Spread(25, 11, whitelist_area)
|
||||
|
||||
for(var/WP in river_nodes)
|
||||
@@ -72,33 +74,42 @@
|
||||
var/list/cardinal_turfs = list()
|
||||
var/list/diagonal_turfs = list()
|
||||
var/logged_turf_type
|
||||
for(var/F in RANGE_TURFS(1, src) - src)
|
||||
var/turf/T = F
|
||||
var/area/new_area = get_area(T)
|
||||
if(!T || (T.density && !ismineralturf(T)) || istype(T, /turf/open/indestructible) || (whitelisted_area && !istype(new_area, whitelisted_area)) || (T.flags_1 & NO_LAVA_GEN_1) )
|
||||
for(var/turf/candidate as anything in RANGE_TURFS(1, src) - src)
|
||||
if(!candidate || (candidate.density && !ismineralturf(candidate)) || isindestructiblefloor(candidate))
|
||||
continue
|
||||
|
||||
if(!logged_turf_type && ismineralturf(T))
|
||||
var/turf/closed/mineral/M = T
|
||||
logged_turf_type = M.turf_type
|
||||
var/area/new_area = get_area(candidate)
|
||||
if((!istype(new_area, whitelisted_area) && whitelisted_area) || (candidate.flags_1 & NO_LAVA_GEN_1))
|
||||
continue
|
||||
|
||||
if(get_dir(src, F) in GLOB.cardinals)
|
||||
cardinal_turfs += F
|
||||
if(!logged_turf_type && ismineralturf(candidate))
|
||||
var/turf/closed/mineral/mineral_candidate = candidate
|
||||
logged_turf_type = mineral_candidate.turf_type
|
||||
|
||||
if(get_dir(src, candidate) in GLOB.cardinals)
|
||||
cardinal_turfs += candidate
|
||||
else
|
||||
diagonal_turfs += F
|
||||
diagonal_turfs += candidate
|
||||
|
||||
for(var/F in cardinal_turfs) //cardinal turfs are always changed but don't always spread
|
||||
var/turf/T = F
|
||||
if(!istype(T, logged_turf_type) && T.ChangeTurf(type, null, CHANGETURF_IGNORE_AIR) && prob(probability))
|
||||
T.Spread(probability - prob_loss, prob_loss, whitelisted_area)
|
||||
for(var/turf/cardinal_candidate as anything in cardinal_turfs) //cardinal turfs are always changed but don't always spread
|
||||
// NOTE: WE ARE SKIPPING CHANGETURF HERE
|
||||
// The calls in this proc only serve to provide a satisfactory (if it's not ALREADY this) check. They do not actually call changeturf
|
||||
// This is safe because this proc can only be run during mapload, and nothing has initialized by now so there's nothing to inherit or delete
|
||||
if(!istype(cardinal_candidate, logged_turf_type) && cardinal_candidate.ChangeTurf(type, baseturfs, CHANGETURF_SKIP) && prob(probability))
|
||||
if(baseturfs)
|
||||
cardinal_candidate.baseturfs = baseturfs
|
||||
cardinal_candidate.Spread(probability - prob_loss, prob_loss, whitelisted_area)
|
||||
|
||||
for(var/F in diagonal_turfs) //diagonal turfs only sometimes change, but will always spread if changed
|
||||
var/turf/T = F
|
||||
if(!istype(T, logged_turf_type) && prob(probability) && T.ChangeTurf(type, null, CHANGETURF_IGNORE_AIR))
|
||||
T.Spread(probability - prob_loss, prob_loss, whitelisted_area)
|
||||
else if(ismineralturf(T))
|
||||
var/turf/closed/mineral/M = T
|
||||
M.ChangeTurf(M.turf_type, null, CHANGETURF_IGNORE_AIR)
|
||||
for(var/turf/diagonal_candidate as anything in diagonal_turfs) //diagonal turfs only sometimes change, but will always spread if changed
|
||||
// Important NOTE: SEE ABOVE
|
||||
if(!istype(diagonal_candidate, logged_turf_type) && prob(probability) && diagonal_candidate.ChangeTurf(type, baseturfs, CHANGETURF_SKIP))
|
||||
if(baseturfs)
|
||||
diagonal_candidate.baseturfs = baseturfs
|
||||
diagonal_candidate.Spread(probability - prob_loss, prob_loss, whitelisted_area)
|
||||
else if(ismineralturf(diagonal_candidate))
|
||||
var/turf/closed/mineral/diagonal_mineral = diagonal_candidate
|
||||
// SEE ABOVE, THIS IS ONLY VERY RARELY SAFE
|
||||
new diagonal_mineral.turf_type(diagonal_mineral)
|
||||
|
||||
|
||||
#undef RANDOM_UPPER_X
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/client/proc/jumptoarea(area/A in GLOB.sortedAreas)
|
||||
/client/proc/jumptoarea(area/A in get_sorted_areas())
|
||||
set name = "Jump to Area"
|
||||
set desc = "Area to jump to"
|
||||
set category = "Admin"
|
||||
@@ -138,21 +138,28 @@
|
||||
usr.forceMove(M.loc)
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Get Key") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/sendmob(mob/M in sortmobs())
|
||||
/client/proc/sendmob(mob/jumper in sortmobs())
|
||||
set category = "Admin.Player Interaction"
|
||||
set name = "Send Mob"
|
||||
if(!src.holder)
|
||||
to_chat(src, "Only administrators may use this command.", confidential=TRUE)
|
||||
return
|
||||
var/area/A = input(usr, "Pick an area.", "Pick an area") in GLOB.sortedAreas|null
|
||||
if(A && istype(A))
|
||||
if(M.forceMove(safepick(get_area_turfs(A))))
|
||||
var/list/sorted_areas = get_sorted_areas()
|
||||
if(!length(sorted_areas))
|
||||
to_chat(src, "No areas found.", confidential = TRUE)
|
||||
return
|
||||
var/area/target_area = input(src, "Pick an area", "Send Mob", sorted_areas)
|
||||
if(isnull(target_area))
|
||||
return
|
||||
if(!istype(target_area))
|
||||
return
|
||||
var/list/turfs = get_area_turfs(target_area)
|
||||
if(length(turfs) && jumper.forceMove(pick(turfs)))
|
||||
message_admins("[key_name_admin(usr)] teleported [ADMIN_LOOKUPFLW(jumper)] to [AREACOORD(jumper)]")
|
||||
|
||||
message_admins("[key_name_admin(usr)] teleported [ADMIN_LOOKUPFLW(M)] to [AREACOORD(A)]")
|
||||
|
||||
var/log_msg = "[key_name(usr)] teleported [key_name(M)] to [AREACOORD(A)]"
|
||||
log_admin(log_msg)
|
||||
admin_ticket_log(M, log_msg, TRUE)
|
||||
else
|
||||
to_chat(src, "Failed to move mob to a valid location.", confidential=TRUE)
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Send Mob") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
var/log_msg = "[key_name(usr)] teleported [key_name(jumper)] to [AREACOORD(jumper)]"
|
||||
log_admin(log_msg)
|
||||
admin_ticket_log(jumper, log_msg, TRUE)
|
||||
else
|
||||
to_chat(src, "Failed to move mob to a valid location.", confidential = TRUE)
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Send Mob") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
@@ -582,7 +582,7 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
|
||||
message_admins(span_adminnotice("[key_name_admin(usr)] used the Test Areas debug command checking [log_message]."))
|
||||
log_admin("[key_name(usr)] used the Test Areas debug command checking [log_message].")
|
||||
|
||||
for(var/area/A in world)
|
||||
for(var/area/A as anything in GLOB.areas)
|
||||
if(on_station)
|
||||
var/turf/picked = safepick(get_area_turfs(A.type))
|
||||
if(picked && is_station_level(picked.z))
|
||||
|
||||
@@ -153,7 +153,7 @@ GLOBAL_LIST_EMPTY(blob_nodes)
|
||||
else
|
||||
L.fully_heal()
|
||||
|
||||
for(var/area/A in GLOB.sortedAreas)
|
||||
for(var/area/A in GLOB.areas)
|
||||
if(!(A.type in GLOB.the_station_areas))
|
||||
continue
|
||||
if(!A.blob_allowed)
|
||||
|
||||
@@ -461,7 +461,7 @@
|
||||
..()
|
||||
var/sanity = 0
|
||||
while(summon_spots.len < SUMMON_POSSIBILITIES && sanity < 100)
|
||||
var/area/summon = pick(GLOB.sortedAreas - summon_spots)
|
||||
var/area/summon = pick(GLOB.areas - summon_spots)
|
||||
if(summon && is_station_level(summon.z) && summon.valid_territory)
|
||||
summon_spots += summon
|
||||
sanity++
|
||||
|
||||
@@ -71,9 +71,9 @@
|
||||
else
|
||||
var/mob/user_mob = user
|
||||
holder = user_mob.client //if its a mob, assign the mob's client to holder
|
||||
bay = locate(/area/centcom/supplypod/loading/one) in GLOB.sortedAreas //Locate the default bay (one) from the centcom map
|
||||
bay = locate(/area/centcom/supplypod/loading/one) in GLOB.areas //Locate the default bay (one) from the centcom map
|
||||
bayNumber = bay.loading_id //Used as quick reference to what bay we're taking items from
|
||||
var/area/pod_storage_area = locate(/area/centcom/supplypod/pod_storage) in GLOB.sortedAreas
|
||||
var/area/pod_storage_area = locate(/area/centcom/supplypod/pod_storage) in GLOB.areas
|
||||
temp_pod = new(pick(get_area_turfs(pod_storage_area))) //Create a new temp_pod in the podStorage area on centcom (so users are free to look at it and change other variables if needed)
|
||||
orderedArea = createOrderedArea(bay) //Order all the turfs in the selected bay (top left to bottom right) to a single list. Used for the "ordered" mode (launchChoice = 1)
|
||||
selector = new(null, holder.mob)
|
||||
|
||||
@@ -179,7 +179,7 @@
|
||||
if (!landingzone)
|
||||
WARNING("[src] couldnt find a Quartermaster/Storage (aka cargobay) area on the station, and as such it has set the supplypod landingzone to the area it resides in.")
|
||||
landingzone = get_area(src)
|
||||
for(var/turf/open/floor/T in landingzone.contents)//uses default landing zone
|
||||
for(var/turf/open/floor/T in landingzone.get_contained_turfs())//uses default landing zone
|
||||
if(is_blocked_turf(T))
|
||||
continue
|
||||
LAZYADD(empty_turfs, T)
|
||||
@@ -196,7 +196,7 @@
|
||||
else
|
||||
if(SO.pack.get_cost() * (0.72*MAX_EMAG_ROCKETS) <= points_to_check) // bulk discount :^)
|
||||
landingzone = GLOB.areas_by_type[pick(GLOB.the_station_areas)] //override default landing zone
|
||||
for(var/turf/open/floor/T in landingzone.contents)
|
||||
for(var/turf/open/floor/T in landingzone.get_contained_turfs())
|
||||
if(is_blocked_turf(T))
|
||||
continue
|
||||
LAZYADD(empty_turfs, T)
|
||||
|
||||
@@ -103,9 +103,8 @@
|
||||
if(!port)
|
||||
return
|
||||
var/list/shuttle_areas = port.shuttle_areas
|
||||
for(var/r in shuttle_areas)
|
||||
var/area/region = r
|
||||
for(var/turf/place in region.contents)
|
||||
for(var/area/region as anything in shuttle_areas)
|
||||
for(var/turf/place as anything in region.get_contained_turfs())
|
||||
if(get_dist(user, place) > 7)
|
||||
continue
|
||||
var/image/pic
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
allowed_areas = make_associative(GLOB.the_station_areas) - safe_area_types + unsafe_area_subtypes
|
||||
|
||||
return safepick(typecache_filter_list(GLOB.sortedAreas,allowed_areas))
|
||||
return safepick(typecache_filter_list(GLOB.areas,allowed_areas))
|
||||
|
||||
/datum/round_event/anomaly/setup()
|
||||
impact_area = findEventArea()
|
||||
@@ -49,4 +49,4 @@
|
||||
if(T)
|
||||
newAnomaly = new anomaly_path(T)
|
||||
if (newAnomaly)
|
||||
announce_to_ghosts(newAnomaly)
|
||||
announce_to_ghosts(newAnomaly)
|
||||
|
||||
@@ -28,27 +28,24 @@
|
||||
M.playsound_local(M, 'sound/ambience/aurora_caelus.ogg', 20, FALSE, pressure_affected = FALSE)
|
||||
|
||||
/datum/round_event/aurora_caelus/start()
|
||||
for(var/area in GLOB.sortedAreas)
|
||||
var/area/A = area
|
||||
for(var/area/A as anything in GLOB.areas)
|
||||
if(initial(A.dynamic_lighting) == DYNAMIC_LIGHTING_IFSTARLIGHT)
|
||||
for(var/turf/open/space/S in A)
|
||||
for(var/turf/open/space/S in A.get_contained_turfs())
|
||||
S.set_light(S.light_range * 3, S.light_power * 2)
|
||||
|
||||
/datum/round_event/aurora_caelus/tick()
|
||||
if(activeFor % 5 == 0)
|
||||
aurora_progress++
|
||||
var/aurora_color = aurora_colors[aurora_progress]
|
||||
for(var/area in GLOB.sortedAreas)
|
||||
var/area/A = area
|
||||
for(var/area/A as anything in GLOB.areas)
|
||||
if(initial(A.dynamic_lighting) == DYNAMIC_LIGHTING_IFSTARLIGHT)
|
||||
for(var/turf/open/space/S in A)
|
||||
for(var/turf/open/space/S in A.get_contained_turfs())
|
||||
S.set_light(l_color = aurora_color)
|
||||
|
||||
/datum/round_event/aurora_caelus/end()
|
||||
for(var/area in GLOB.sortedAreas)
|
||||
var/area/A = area
|
||||
for(var/area/A as anything in GLOB.areas)
|
||||
if(initial(A.dynamic_lighting) == DYNAMIC_LIGHTING_IFSTARLIGHT)
|
||||
for(var/turf/open/space/S in A)
|
||||
for(var/turf/open/space/S in A.get_contained_turfs())
|
||||
fade_to_black(S)
|
||||
priority_announce("The aurora caelus event is now ending. Starlight conditions will slowly return to normal. When this has concluded, please return to your workplace and continue work as normal. Have a pleasant shift, [station_name()], and thank you for watching with us.",
|
||||
sound = 'sound/misc/notice2.ogg',
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
severity = rand(1,3)
|
||||
for(var/i in 1 to severity)
|
||||
var/picked_area = pick_n_take(potential_areas)
|
||||
for(var/area/A in world)
|
||||
for(var/area/A as anything in GLOB.areas)
|
||||
if(istype(A, picked_area))
|
||||
areasToOpen += A
|
||||
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
|
||||
var/obj/structure/spacevine/SV = new()
|
||||
|
||||
for(var/area/maintenance/A in world)
|
||||
for(var/turf/F in A)
|
||||
for(var/area/maintenance/A in GLOB.areas)
|
||||
for(var/turf/F as anything in A.get_contained_turfs())
|
||||
if(F.Enter(SV))
|
||||
turfs += F
|
||||
|
||||
|
||||
@@ -76,6 +76,6 @@
|
||||
///Subtypes from the above that actually should explode.
|
||||
var/list/unsafe_area_subtypes = typecacheof(list(/area/engine/break_room))
|
||||
allowed_areas = make_associative(GLOB.the_station_areas) - safe_area_types + unsafe_area_subtypes
|
||||
var/list/possible_areas = typecache_filter_list(GLOB.sortedAreas,allowed_areas)
|
||||
var/list/possible_areas = typecache_filter_list(GLOB.areas, allowed_areas)
|
||||
if (length(possible_areas))
|
||||
return pick(possible_areas)
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
/proc/create_all_lighting_objects()
|
||||
for(var/area/A in world)
|
||||
for(var/area/A as anything in GLOB.areas)
|
||||
if(!IS_DYNAMIC_LIGHTING(A))
|
||||
continue
|
||||
|
||||
for(var/turf/T in A)
|
||||
|
||||
for(var/turf/T as anything in A.get_contained_turfs())
|
||||
if(!IS_DYNAMIC_LIGHTING(T))
|
||||
continue
|
||||
|
||||
|
||||
@@ -59,14 +59,13 @@
|
||||
var/x = round((world.maxx - width)/2)
|
||||
var/y = round((world.maxy - height)/2)
|
||||
|
||||
var/datum/space_level/level = SSmapping.add_new_zlevel(name, secret ? ZTRAITS_AWAY_SECRET : ZTRAITS_AWAY)
|
||||
var/datum/parsed_map/parsed = load_map(file(mappath), x, y, level.z_value, no_changeturf=(SSatoms.initialized == INITIALIZATION_INSSATOMS), placeOnTop=TRUE)
|
||||
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=TRUE, new_z = TRUE)
|
||||
var/list/bounds = parsed.bounds
|
||||
if(!bounds)
|
||||
return FALSE
|
||||
|
||||
repopulate_sorted_areas()
|
||||
|
||||
require_area_resort()
|
||||
//initialize things that are normally initialized after map load
|
||||
parsed.initTemplateBounds()
|
||||
smooth_zlevel(world.maxz)
|
||||
@@ -79,9 +78,9 @@
|
||||
T = locate(T.x - round(width/2) , T.y - round(height/2) , T.z)
|
||||
if(!T)
|
||||
return
|
||||
if(T.x+width > world.maxx)
|
||||
if((T.x+width) - 1 > world.maxx)
|
||||
return
|
||||
if(T.y+height > world.maxy)
|
||||
if((T.y+height) - 1 > world.maxy)
|
||||
return
|
||||
|
||||
// Accept cached maps, but don't save them automatically - we don't want
|
||||
@@ -94,8 +93,7 @@
|
||||
if(!bounds)
|
||||
return
|
||||
|
||||
if(!SSmapping.loading_ruins) //Will be done manually during mapping ss init
|
||||
repopulate_sorted_areas()
|
||||
require_area_resort()
|
||||
|
||||
//initialize things that are normally initialized after map load
|
||||
parsed.initTemplateBounds()
|
||||
|
||||
@@ -1,25 +1,24 @@
|
||||
// global datum that will preload variables on atoms instanciation
|
||||
GLOBAL_VAR_INIT(use_preloader, FALSE)
|
||||
GLOBAL_DATUM_INIT(_preloader, /datum/map_preloader, new)
|
||||
GLOBAL_LIST_INIT(_preloader_attributes, null)
|
||||
GLOBAL_LIST_INIT(_preloader_path, null)
|
||||
|
||||
/// Preloader datum
|
||||
/datum/map_preloader
|
||||
parent_type = /datum
|
||||
var/list/attributes
|
||||
var/target_path
|
||||
|
||||
/world/proc/preloader_setup(list/the_attributes, path)
|
||||
if(the_attributes.len)
|
||||
GLOB.use_preloader = TRUE
|
||||
var/datum/map_preloader/preloader_local = GLOB._preloader
|
||||
preloader_local.attributes = the_attributes
|
||||
preloader_local.target_path = path
|
||||
GLOB._preloader_attributes = the_attributes
|
||||
GLOB._preloader_path = path
|
||||
|
||||
/world/proc/preloader_load(atom/what)
|
||||
GLOB.use_preloader = FALSE
|
||||
var/datum/map_preloader/preloader_local = GLOB._preloader
|
||||
for(var/attribute in preloader_local.attributes)
|
||||
var/value = preloader_local.attributes[attribute]
|
||||
var/list/attributes = GLOB._preloader_attributes
|
||||
for(var/attribute in attributes)
|
||||
var/value = attributes[attribute]
|
||||
if(islist(value))
|
||||
value = deepCopyList(value)
|
||||
#ifdef TESTING
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
/datum/map_template/ruin/proc/try_to_place(z,allowed_areas,turf/forced_turf)
|
||||
/datum/map_template/ruin/proc/try_to_place(z, list/allowed_areas_typecache, turf/forced_turf, clear_below)
|
||||
var/sanity = forced_turf ? 1 : PLACEMENT_TRIES
|
||||
while(sanity > 0)
|
||||
sanity--
|
||||
@@ -6,18 +6,22 @@
|
||||
var/height_border = TRANSITIONEDGE + SPACERUIN_MAP_EDGE_PAD + round(height / 2)
|
||||
var/turf/central_turf = locate(rand(width_border, world.maxx - width_border), rand(height_border, world.maxy - height_border), z)
|
||||
var/valid = TRUE
|
||||
var/list/affected_turfs = get_affected_turfs(central_turf,1)
|
||||
var/list/affected_areas = list()
|
||||
|
||||
for(var/turf/check in get_affected_turfs(central_turf,1))
|
||||
var/area/new_area = get_area(check)
|
||||
for(var/turf/check in affected_turfs)
|
||||
// Use assoc lists to move this out, it's easier that way
|
||||
if(check.flags_1 & NO_RUINS_1)
|
||||
valid = FALSE
|
||||
else
|
||||
valid = FALSE // set to false before we check
|
||||
for(var/type in allowed_areas)
|
||||
if(istype(new_area, type)) // it's at least one of our types so it's whitelisted
|
||||
valid = TRUE
|
||||
break
|
||||
if(!valid)
|
||||
break
|
||||
|
||||
var/area/new_area = get_area(check)
|
||||
affected_areas[new_area] = TRUE
|
||||
|
||||
// This is faster yes. Only BARELY but it is faster
|
||||
for(var/area/affct_area as anything in affected_areas)
|
||||
if(!allowed_areas_typecache[affct_area.type])
|
||||
valid = FALSE
|
||||
break
|
||||
|
||||
if(!valid)
|
||||
@@ -25,29 +29,32 @@
|
||||
|
||||
testing("Ruin \"[name]\" placed at ([central_turf.x], [central_turf.y], [central_turf.z])")
|
||||
|
||||
for(var/i in get_affected_turfs(central_turf, 1))
|
||||
var/turf/T = i
|
||||
for(var/obj/structure/spawner/nest in T)
|
||||
qdel(nest)
|
||||
for(var/mob/living/simple_animal/monster in T)
|
||||
qdel(monster)
|
||||
for(var/obj/structure/flora/ash/plant in T)
|
||||
qdel(plant)
|
||||
if(clear_below)
|
||||
var/list/static/clear_below_typecache = typecacheof(list(
|
||||
/obj/structure/spawner,
|
||||
/mob/living/simple_animal,
|
||||
/obj/structure/flora
|
||||
))
|
||||
for(var/turf/T as anything in affected_turfs)
|
||||
for(var/atom/thing as anything in T)
|
||||
if(clear_below_typecache[thing.type])
|
||||
qdel(thing)
|
||||
|
||||
load(central_turf,centered = TRUE)
|
||||
loaded++
|
||||
|
||||
for(var/turf/T in get_affected_turfs(central_turf, 1))
|
||||
for(var/turf/T in affected_turfs)
|
||||
T.flags_1 |= NO_RUINS_1
|
||||
|
||||
new /obj/effect/landmark/ruin(central_turf, src)
|
||||
return central_turf
|
||||
|
||||
|
||||
/proc/seedRuins(list/z_levels = null, budget = 0, whitelist = list(/area/space), list/potentialRuins)
|
||||
/proc/seedRuins(list/z_levels = null, budget = 0, whitelist = list(/area/space), list/potentialRuins, clear_below = FALSE)
|
||||
if(!z_levels || !z_levels.len)
|
||||
WARNING("No Z levels provided - Not generating ruins")
|
||||
return
|
||||
var/list/whitelist_typecache = typecacheof(whitelist)
|
||||
|
||||
for(var/zl in z_levels)
|
||||
var/turf/T = locate(1, 1, zl)
|
||||
@@ -111,7 +118,7 @@
|
||||
else
|
||||
break outer
|
||||
|
||||
placed_turf = current_pick.try_to_place(target_z,whitelist,forced_turf)
|
||||
placed_turf = current_pick.try_to_place(target_z,whitelist_typecache,forced_turf,clear_below)
|
||||
if(!placed_turf)
|
||||
continue
|
||||
else
|
||||
|
||||
@@ -14,11 +14,11 @@
|
||||
turf_type = /turf/open/space/transit
|
||||
|
||||
/datum/turf_reservation/proc/Release()
|
||||
var/v = reserved_turfs.Copy()
|
||||
for(var/i in reserved_turfs)
|
||||
reserved_turfs -= i
|
||||
SSmapping.used_turfs -= i
|
||||
SSmapping.reserve_turfs(v)
|
||||
var/list/reserved_copy = reserved_turfs.Copy()
|
||||
SSmapping.used_turfs -= reserved_turfs
|
||||
reserved_turfs = list()
|
||||
// Makes the linter happy, even tho we don't await this
|
||||
INVOKE_ASYNC(SSmapping, /datum/controller/subsystem/mapping/proc/reserve_turfs, reserved_copy)
|
||||
|
||||
/datum/turf_reservation/proc/Reserve(width, height, zlevel)
|
||||
if(width > world.maxx || height > world.maxy || width < 1 || height < 1)
|
||||
|
||||
@@ -22,122 +22,141 @@
|
||||
neigbours[TEXT_WEST] = P.spl
|
||||
P.spl.neigbours[TEXT_EAST] = src
|
||||
|
||||
#define CHORDS_TO_1D(x, y, grid_diameter) ((x) + ((y) - 1) * (grid_diameter))
|
||||
/datum/space_transition_point //this is explicitly utilitarian datum type made specially for the space map generation and are absolutely unusable for anything else
|
||||
var/list/neigbours = list()
|
||||
var/x
|
||||
var/y
|
||||
var/datum/space_level/spl
|
||||
|
||||
/datum/space_transition_point/New(nx, ny, list/point_grid)
|
||||
if(!point_grid)
|
||||
/datum/space_transition_point/New(nx, ny, list/grid)
|
||||
if(!grid)
|
||||
qdel(src)
|
||||
return
|
||||
var/list/L = point_grid[1]
|
||||
if(nx > point_grid.len || ny > L.len)
|
||||
var/grid_diameter = sqrt(length(grid))
|
||||
if(nx > grid_diameter || ny > grid_diameter)
|
||||
stack_trace("Attempted to set a position outside the size of [grid_diameter]")
|
||||
qdel(src)
|
||||
return
|
||||
x = nx
|
||||
y = ny
|
||||
if(point_grid[x][y])
|
||||
var/position = CHORDS_TO_1D(x, y, grid_diameter)
|
||||
if(grid[position])
|
||||
return
|
||||
point_grid[x][y] = src
|
||||
grid[position] = src
|
||||
|
||||
/datum/space_transition_point/proc/set_neigbours(list/grid)
|
||||
var/max_X = grid.len
|
||||
var/list/max_Y = grid[1]
|
||||
max_Y = max_Y.len
|
||||
/datum/space_transition_point/proc/set_neigbours(list/grid, size)
|
||||
neigbours.Cut()
|
||||
if(x+1 <= max_X)
|
||||
neigbours |= grid[x+1][y]
|
||||
|
||||
if(x+1 <= size)
|
||||
neigbours |= grid[CHORDS_TO_1D(x+1, y, size)]
|
||||
if(x-1 >= 1)
|
||||
neigbours |= grid[x-1][y]
|
||||
if(y+1 <= max_Y)
|
||||
neigbours |= grid[x][y+1]
|
||||
neigbours |= grid[CHORDS_TO_1D(x-1, y, size)]
|
||||
if(y+1 <= size)
|
||||
neigbours |= grid[CHORDS_TO_1D(x, y + 1, size)]
|
||||
if(y-1 >= 1)
|
||||
neigbours |= grid[x][y-1]
|
||||
neigbours |= grid[CHORDS_TO_1D(x, y - 1, size)]
|
||||
|
||||
/datum/controller/subsystem/mapping/proc/setup_map_transitions() //listamania
|
||||
var/list/SLS = list()
|
||||
var/list/transition_levels = list()
|
||||
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)
|
||||
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
|
||||
for(var/i = 1, i<=conf_set_len*2+1, i++)
|
||||
for(var/j = 1, j<=conf_set_len*2+1, j++)
|
||||
P = new/datum/space_transition_point(i,j, point_grid)
|
||||
point_grid[i][j] = P
|
||||
grid.Add(P)
|
||||
for(var/datum/space_transition_point/pnt in grid)
|
||||
pnt.set_neigbours(point_grid)
|
||||
P = point_grid[conf_set_len+1][conf_set_len+1]
|
||||
for(var/datum/space_level/level as anything in cached_z_list)
|
||||
if (level.linkage == CROSSLINKED)
|
||||
transition_levels.Add(level)
|
||||
|
||||
var/grid_diameter = (length(transition_levels) * 2) + 1
|
||||
var/list/grid = new /list(grid_diameter ** 2)
|
||||
|
||||
var/datum/space_transition_point/point
|
||||
for(var/x in 1 to grid_diameter)
|
||||
for(var/y in 1 to grid_diameter)
|
||||
point = new/datum/space_transition_point(x, y, grid)
|
||||
grid[CHORDS_TO_1D(x, y, grid_diameter)] = point
|
||||
for(point as anything in grid)
|
||||
point.set_neigbours(grid, grid_diameter)
|
||||
|
||||
var/center = round(grid_diameter / 2)
|
||||
point = grid[CHORDS_TO_1D(grid_diameter, center, center)]
|
||||
grid.Cut()
|
||||
|
||||
var/list/transition_pick = transition_levels.Copy()
|
||||
var/list/possible_points = list()
|
||||
var/list/used_points = list()
|
||||
grid.Cut()
|
||||
while(SLS.len)
|
||||
var/datum/space_level/D = pick_n_take(SLS)
|
||||
D.xi = P.x
|
||||
D.yi = P.y
|
||||
P.spl = D
|
||||
possible_points |= P.neigbours
|
||||
used_points |= P
|
||||
while(transition_pick.len)
|
||||
var/datum/space_level/level = pick_n_take(transition_pick)
|
||||
level.xi = point.x
|
||||
level.yi = point.y
|
||||
point.spl = level
|
||||
possible_points |= point.neigbours
|
||||
used_points |= point
|
||||
possible_points.Remove(used_points)
|
||||
D.set_neigbours(used_points)
|
||||
P = pick(possible_points)
|
||||
level.set_neigbours(used_points)
|
||||
point = pick(possible_points)
|
||||
CHECK_TICK
|
||||
|
||||
// Now that we've handed out neighbors, we're gonna handle an edge case
|
||||
// Need to check if all our levels have neighbors in all directions
|
||||
// If they don't, we'll make them wrap all the way around to the other side of the grid
|
||||
for(var/direction in GLOB.cardinals)
|
||||
var/dir = "[direction]"
|
||||
var/inverse = "[turn(direction, 180)]"
|
||||
for(var/datum/space_level/level as anything in transition_levels)
|
||||
// If we have something in this dir that isn't just us, continue on
|
||||
if(level.neigbours[dir] && level.neigbours[dir] != level)
|
||||
continue
|
||||
var/datum/space_level/head = level
|
||||
while(head.neigbours[inverse] && head.neigbours[inverse] != head)
|
||||
head = head.neigbours[inverse]
|
||||
|
||||
// Alllright we've landed on someone who we can wrap around onto safely, let's make that connection yeah?
|
||||
head.neigbours[inverse] = level
|
||||
level.neigbours[dir] = head
|
||||
|
||||
//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
|
||||
|
||||
var/list/x_pos_beginning = list(1, 1, world.maxx - TRANSITIONEDGE, 1) //x values of the lowest-leftest turfs of the respective 4 blocks on each side of zlevel
|
||||
var/list/y_pos_beginning = list(world.maxy - TRANSITIONEDGE, 1, 1 + TRANSITIONEDGE, 1 + TRANSITIONEDGE) //y values respectively
|
||||
var/inner_max_x = world.maxx - TRANSITIONEDGE
|
||||
var/inner_max_y = world.maxy - TRANSITIONEDGE
|
||||
var/list/x_pos_beginning = list(1, 1, inner_max_x, 1) //x values of the lowest-leftest turfs of the respective 4 blocks on each side of zlevel
|
||||
var/list/y_pos_beginning = list(inner_max_y, 1, 1 + TRANSITIONEDGE, 1 + TRANSITIONEDGE) //y values respectively
|
||||
var/list/x_pos_ending = list(world.maxx, world.maxx, world.maxx, 1 + TRANSITIONEDGE) //x values of the highest-rightest turfs of the respective 4 blocks on each side of zlevel
|
||||
var/list/y_pos_ending = list(world.maxy, 1 + TRANSITIONEDGE, world.maxy - TRANSITIONEDGE, world.maxy - TRANSITIONEDGE) //y values respectively
|
||||
var/list/x_pos_transition = list(1, 1, TRANSITIONEDGE + 2, world.maxx - TRANSITIONEDGE - 1) //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 - 1, 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
|
||||
var/list/y_pos_ending = list(world.maxy, 1 + TRANSITIONEDGE, inner_max_y, inner_max_y) //y values respectively
|
||||
var/list/x_pos_transition = list(1, 1, TRANSITIONEDGE + 2, inner_max_x - 1) //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, inner_max_y - 1, 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/I in cached_z_list)
|
||||
var/datum/space_level/D = I
|
||||
if(!D.neigbours.len)
|
||||
for(var/datum/space_level/level as anything in cached_z_list)
|
||||
if(!level.neigbours.len)
|
||||
continue
|
||||
var/zlevelnumber = D.z_value
|
||||
var/zlevelnumber = level.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)
|
||||
var/dirside = 2**(side-1)
|
||||
var/zdestination = zlevelnumber
|
||||
if(D.neigbours["[dirside]"] && D.neigbours["[dirside]"] != D)
|
||||
D = D.neigbours["[dirside]"]
|
||||
zdestination = D.z_value
|
||||
else
|
||||
dirside = turn(dirside, 180)
|
||||
while(D.neigbours["[dirside]"] && D.neigbours["[dirside]"] != D)
|
||||
D = D.neigbours["[dirside]"]
|
||||
zdestination = D.z_value
|
||||
D = I
|
||||
var/x_target = x_pos_transition[side] == 1 ? 0 : x_pos_transition[side]
|
||||
var/y_target = y_pos_transition[side] == 1 ? 0 : y_pos_transition[side]
|
||||
var/datum/space_level/neighbor = level.neigbours["[dirside]"]
|
||||
var/zdestination = neighbor.z_value
|
||||
|
||||
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_x = x_target || S.x
|
||||
S.destination_y = y_target || S.y
|
||||
S.destination_z = zdestination
|
||||
|
||||
// Mirage border code
|
||||
var/mirage_dir
|
||||
if(S.x == 1 + TRANSITIONEDGE)
|
||||
mirage_dir |= WEST
|
||||
else if(S.x == world.maxx - TRANSITIONEDGE)
|
||||
else if(S.x == inner_max_x)
|
||||
mirage_dir |= EAST
|
||||
if(S.y == 1 + TRANSITIONEDGE)
|
||||
mirage_dir |= SOUTH
|
||||
else if(S.y == world.maxy - TRANSITIONEDGE)
|
||||
else if(S.y == inner_max_y)
|
||||
mirage_dir |= NORTH
|
||||
if(!mirage_dir)
|
||||
continue
|
||||
|
||||
var/turf/place = locate(S.destination_x, S.destination_y, S.destination_z)
|
||||
var/turf/place = locate(S.destination_x, S.destination_y, zdestination)
|
||||
S.AddComponent(/datum/component/mirage_border, place, mirage_dir)
|
||||
|
||||
#undef CHORDS_TO_1D
|
||||
|
||||
@@ -14,9 +14,10 @@
|
||||
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_TRAITS])
|
||||
build_area_turfs(I, FALSE)
|
||||
z_list += S
|
||||
|
||||
/datum/controller/subsystem/mapping/proc/add_new_zlevel(name, traits = list(), z_type = /datum/space_level)
|
||||
/datum/controller/subsystem/mapping/proc/add_new_zlevel(name, traits = list(), z_type = /datum/space_level, filled_with_space = TRUE, contain_turfs = TRUE)
|
||||
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_NEW_Z, args)
|
||||
var/new_z = z_list.len + 1
|
||||
if (world.maxz < new_z)
|
||||
@@ -24,6 +25,8 @@
|
||||
CHECK_TICK
|
||||
// TODO: sleep here if the Z level needs to be cleared
|
||||
var/datum/space_level/S = new z_type(new_z, name, traits)
|
||||
if(contain_turfs)
|
||||
build_area_turfs(new_z, filled_with_space)
|
||||
z_list += S
|
||||
return S
|
||||
|
||||
|
||||
@@ -404,8 +404,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
to_chat(usr, "Not when you're not dead!")
|
||||
return
|
||||
var/list/filtered = list()
|
||||
for(var/V in GLOB.sortedAreas)
|
||||
var/area/A = V
|
||||
for(var/area/A as anything in get_sorted_areas())
|
||||
if(!A.hidden)
|
||||
filtered += A
|
||||
var/area/thearea = input("Area to jump to", "BOOYEA") as null|anything in filtered
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
var/list/obj/structure/cable/cables = list()
|
||||
var/list/atom/atoms = list()
|
||||
|
||||
repopulate_sorted_areas()
|
||||
require_area_resort()
|
||||
|
||||
for(var/L in block(locate(bounds[MAP_MINX], bounds[MAP_MINY], SSmapping.station_start),
|
||||
locate(bounds[MAP_MAXX], bounds[MAP_MAXY], z_offset - 1)))
|
||||
|
||||
@@ -133,19 +133,21 @@ GLOBAL_DATUM_INIT(keycard_events, /datum/events, new)
|
||||
|
||||
GLOBAL_VAR_INIT(emergency_access, FALSE)
|
||||
/proc/make_maint_all_access()
|
||||
for(var/area/maintenance/A in world)
|
||||
for(var/obj/machinery/door/airlock/D in A)
|
||||
D.emergency = TRUE
|
||||
D.update_icon(0)
|
||||
for(var/area/maintenance/A in GLOB.areas)
|
||||
for(var/turf/in_area as anything in A.get_contained_turfs())
|
||||
for(var/obj/machinery/door/airlock/D in in_area)
|
||||
D.emergency = TRUE
|
||||
D.update_icon(ALL, 0)
|
||||
minor_announce("Access restrictions on maintenance and external airlocks have been lifted.", "Attention! Station-wide emergency declared!",1)
|
||||
GLOB.emergency_access = TRUE
|
||||
SSblackbox.record_feedback("nested tally", "keycard_auths", 1, list("emergency maintenance access", "enabled"))
|
||||
|
||||
/proc/revoke_maint_all_access()
|
||||
for(var/area/maintenance/A in world)
|
||||
for(var/obj/machinery/door/airlock/D in A)
|
||||
D.emergency = FALSE
|
||||
D.update_icon(0)
|
||||
for(var/area/maintenance/A in GLOB.areas)
|
||||
for(var/turf/in_area as anything in A.get_contained_turfs())
|
||||
for(var/obj/machinery/door/airlock/D in in_area)
|
||||
D.emergency = FALSE
|
||||
D.update_icon(ALL, 0)
|
||||
minor_announce("Access restrictions in maintenance areas have been restored.", "Attention! Station-wide emergency rescinded:")
|
||||
GLOB.emergency_access = FALSE
|
||||
SSblackbox.record_feedback("nested tally", "keycard_auths", 1, list("emergency maintenance access", "disabled"))
|
||||
@@ -157,4 +159,4 @@ GLOBAL_VAR_INIT(emergency_access, FALSE)
|
||||
|
||||
#undef KEYCARD_RED_ALERT
|
||||
#undef KEYCARD_EMERGENCY_MAINTENANCE_ACCESS
|
||||
#undef KEYCARD_BSA_UNLOCK
|
||||
#undef KEYCARD_BSA_UNLOCK
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
areas = list()
|
||||
|
||||
var/list/new_latejoin = list()
|
||||
for(var/area/shuttle/arrival/A in GLOB.sortedAreas)
|
||||
for(var/area/shuttle/arrival/A in GLOB.areas)
|
||||
for(var/obj/structure/chair/C in A)
|
||||
new_latejoin += C
|
||||
if(!console)
|
||||
|
||||
@@ -388,7 +388,7 @@
|
||||
if(time_left <= 50 && !sound_played) //4 seconds left:REV UP THOSE ENGINES BOYS. - should sync up with the launch
|
||||
sound_played = 1 //Only rev them up once.
|
||||
var/list/areas = list()
|
||||
for(var/area/shuttle/escape/E in GLOB.sortedAreas)
|
||||
for(var/area/shuttle/escape/E in GLOB.areas)
|
||||
areas += E
|
||||
hyperspace_sound(HYPERSPACE_WARMUP, areas)
|
||||
|
||||
@@ -400,7 +400,7 @@
|
||||
|
||||
//now move the actual emergency shuttle to its transit dock
|
||||
var/list/areas = list()
|
||||
for(var/area/shuttle/escape/E in GLOB.sortedAreas)
|
||||
for(var/area/shuttle/escape/E in GLOB.areas)
|
||||
areas += E
|
||||
hyperspace_sound(HYPERSPACE_LAUNCH, areas)
|
||||
enterTransit()
|
||||
@@ -415,7 +415,7 @@
|
||||
if(SHUTTLE_ESCAPE)
|
||||
if(sound_played && time_left <= HYPERSPACE_END_TIME)
|
||||
var/list/areas = list()
|
||||
for(var/area/shuttle/escape/E in GLOB.sortedAreas)
|
||||
for(var/area/shuttle/escape/E in GLOB.areas)
|
||||
areas += E
|
||||
hyperspace_sound(HYPERSPACE_END, areas)
|
||||
if(time_left <= PARALLAX_LOOP_TIME)
|
||||
|
||||
@@ -151,7 +151,9 @@ All ShuttleMove procs go here
|
||||
return TRUE
|
||||
|
||||
contents -= oldT
|
||||
turfs_to_uncontain += oldT
|
||||
underlying_old_area.contents += oldT
|
||||
underlying_old_area.contained_turfs += oldT
|
||||
oldT.change_area(src, underlying_old_area)
|
||||
//The old turf has now been given back to the area that turf originaly belonged to
|
||||
|
||||
@@ -159,7 +161,9 @@ All ShuttleMove procs go here
|
||||
parallax_movedir = old_dest_area.parallax_movedir
|
||||
|
||||
old_dest_area.contents -= newT
|
||||
old_dest_area.turfs_to_uncontain += newT
|
||||
contents += newT
|
||||
contained_turfs += newT
|
||||
newT.change_area(old_dest_area, src)
|
||||
return TRUE
|
||||
|
||||
|
||||
@@ -482,7 +482,9 @@
|
||||
if(!oldT || !istype(oldT.loc, area_type))
|
||||
continue
|
||||
var/area/old_area = oldT.loc
|
||||
old_area.turfs_to_uncontain += oldT
|
||||
underlying_area.contents += oldT
|
||||
underlying_area.contained_turfs += oldT
|
||||
oldT.change_area(old_area, underlying_area)
|
||||
oldT.empty(FALSE)
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@
|
||||
#include "code\__DEFINES\time.dm"
|
||||
#include "code\__DEFINES\tools.dm"
|
||||
#include "code\__DEFINES\traits.dm"
|
||||
#include "code\__DEFINES\turf_flags.dm"
|
||||
#include "code\__DEFINES\turfs.dm"
|
||||
#include "code\__DEFINES\typeids.dm"
|
||||
#include "code\__DEFINES\vehicles.dm"
|
||||
#include "code\__DEFINES\vv.dm"
|
||||
@@ -275,6 +275,7 @@
|
||||
#include "code\controllers\subsystem\acid.dm"
|
||||
#include "code\controllers\subsystem\adjacent_air.dm"
|
||||
#include "code\controllers\subsystem\air.dm"
|
||||
#include "code\controllers\subsystem\area_contents.dm"
|
||||
#include "code\controllers\subsystem\assets.dm"
|
||||
#include "code\controllers\subsystem\atoms.dm"
|
||||
#include "code\controllers\subsystem\augury.dm"
|
||||
|
||||
Reference in New Issue
Block a user