diff --git a/code/__DEFINES/flags.dm b/code/__DEFINES/flags.dm
index f566492ec3..43cdbcb646 100644
--- a/code/__DEFINES/flags.dm
+++ b/code/__DEFINES/flags.dm
@@ -30,12 +30,12 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
#define ADMIN_SPAWNED_1 (1<<15) //was this spawned by an admin? used for stat tracking stuff.
//turf-only flags
-#define NOJAUNT_1 (1<<0)
-#define UNUSED_TRANSIT_TURF_1 (1<<1)
-#define CAN_BE_DIRTY_1 (1<<2) // If a turf can be made dirty at roundstart. This is also used in areas.
-#define NO_DEATHRATTLE_1 (1<<4) // Do not notify deadchat about any deaths that occur on this turf.
-#define NO_RUINS_1 (1<<5) //Blocks ruins spawning on the turf
-#define NO_LAVA_GEN_1 (1<<6) //Blocks lava rivers being generated on the turf
+#define NOJAUNT_1 (1<<0)
+#define UNUSED_RESERVATION_TURF_1 (1<<1)
+#define CAN_BE_DIRTY_1 (1<<2) // If a turf can be made dirty at roundstart. This is also used in areas.
+#define NO_DEATHRATTLE_1 (1<<4) // Do not notify deadchat about any deaths that occur on this turf.
+#define NO_RUINS_1 (1<<5) //Blocks ruins spawning on the turf
+#define NO_LAVA_GEN_1 (1<<6) //Blocks lava rivers being generated on the turf
/*
These defines are used specifically with the atom/pass_flags bitmask
diff --git a/code/__DEFINES/maps.dm b/code/__DEFINES/maps.dm
index c86e47709c..98d022d27e 100644
--- a/code/__DEFINES/maps.dm
+++ b/code/__DEFINES/maps.dm
@@ -33,7 +33,7 @@ require only minor tweaks.
#define ZTRAIT_STATION "Station"
#define ZTRAIT_MINING "Mining"
#define ZTRAIT_REEBE "Reebe"
-#define ZTRAIT_TRANSIT "Transit"
+#define ZTRAIT_RESERVED "Transit/Reserved"
#define ZTRAIT_AWAY "Away Mission"
#define ZTRAIT_SPACE_RUINS "Space Ruins"
#define ZTRAIT_LAVA_RUINS "Lava Ruins"
@@ -76,6 +76,8 @@ require only minor tweaks.
#define CAMERA_LOCK_CENTCOM 4
#define CAMERA_LOCK_REEBE 8
+//Reserved/Transit turf type
+#define RESERVED_TURF_TYPE /turf/open/space/basic //What the turf is when not being used
//Ruin Generation
diff --git a/code/__HELPERS/level_traits.dm b/code/__HELPERS/level_traits.dm
index 4d20c9b513..b73a0aa83d 100644
--- a/code/__HELPERS/level_traits.dm
+++ b/code/__HELPERS/level_traits.dm
@@ -9,7 +9,7 @@
#define is_reebe(z) SSmapping.level_trait(z, ZTRAIT_REEBE)
-#define is_transit_level(z) SSmapping.level_trait(z, ZTRAIT_TRANSIT)
+#define is_reserved_level(z) SSmapping.level_trait(z, ZTRAIT_RESERVED)
#define is_away_level(z) SSmapping.level_trait(z, ZTRAIT_AWAY)
diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm
index 5ef8dc6d1b..aa872fa75e 100644
--- a/code/_globalvars/bitfields.dm
+++ b/code/_globalvars/bitfields.dm
@@ -111,8 +111,8 @@ GLOBAL_LIST_INIT(bitfields, list(
),
"flags_1" = list(
"NOJAUNT_1" = NOJAUNT_1,
- "NODROP_1 / UNUSED_TRANSIT_TURF_1 (turfs)" = NODROP_1,
- "NOBLUDGEON_1 / CAN_BE_DIRTY_1 (turfs)" = NOBLUDGEON_1,
+ "UNUSED_RESERVATION_TURF_1" = UNUSED_RESERVATION_TURF_1,
+ "CAN_BE_DIRTY_1" = CAN_BE_DIRTY_1,
"HEAR_1 / NO_DEATHRATTLE_1 (turfs)" = HEAR_1,
"CHECK_RICOCHET_1 / NO_RUINS_1 (turfs)" = CHECK_RICOCHET_1,
"CONDUCT_1 / NO_LAVA_GEN_1" = CONDUCT_1,
diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm
index 2d99012881..e2698670e9 100644
--- a/code/controllers/subsystem/mapping.dm
+++ b/code/controllers/subsystem/mapping.dm
@@ -21,6 +21,11 @@ SUBSYSTEM_DEF(mapping)
var/list/areas_in_z = list()
var/loading_ruins = FALSE
+ 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
+
+ var/clearing_reserved_turfs = FALSE
// Z-manager stuff
var/station_start // should only be used for maploading-related tasks
@@ -41,6 +46,8 @@ SUBSYSTEM_DEF(mapping)
/datum/controller/subsystem/mapping/Initialize(timeofday)
+ if(initialized)
+ return
if(config.defaulted)
to_chat(world, "Unable to load next map config, defaulting to Box Station")
loader = new
@@ -58,12 +65,13 @@ SUBSYSTEM_DEF(mapping)
++space_levels_so_far
empty_space = add_new_zlevel("Empty Area [space_levels_so_far]", list(ZTRAIT_LINKAGE = CROSSLINKED))
// and the transit level
- transit = add_new_zlevel("Transit", list(ZTRAIT_TRANSIT = TRUE))
+ transit = add_new_zlevel("Transit/Reserved", list(ZTRAIT_RESERVED = TRUE))
// Pick a random away mission.
if(CONFIG_GET(flag/roundstart_away))
createRandomZlevel()
+
// Generate mining ruins
loading_ruins = TRUE
var/list/lava_ruins = levels_by_trait(ZTRAIT_LAVA_RUINS)
@@ -83,12 +91,42 @@ SUBSYSTEM_DEF(mapping)
setup_map_transitions()
generate_station_area_list()
QDEL_NULL(loader)
+ initialize_reserved_level()
..()
/* Nuke threats, for making the blue tiles on the station go RED
Used by the AI doomsday and the self destruct nuke.
*/
+/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
+ clearing_reserved_turfs = TRUE
+ SSshuttle.transit_requesters.Cut()
+ message_admins("Clearing dynamic reservation space.")
+ var/list/obj/docking_port/mobile/in_transit = list()
+ for(var/i in SSshuttle.transit)
+ var/obj/docking_port/stationary/transit/T = i
+ if(!istype(T))
+ continue
+ in_transit[T] = T.get_docked()
+ var/go_ahead = world.time + wipe_safety_delay
+ if(in_transit.len)
+ message_admins("Shuttles in transit detected. Attempting to fast travel. Timeout is [wipe_safety_delay/10] seconds.")
+ var/list/cleared = list()
+ for(var/i in in_transit)
+ INVOKE_ASYNC(src, .proc/safety_clear_transit_dock, i, in_transit[i], cleared)
+ UNTIL((go_ahead < world.time) || (cleared.len == in_transit.len))
+ do_wipe_turf_reservations()
+ clearing_reserved_turfs = FALSE
+
+/datum/controller/subsystem/mapping/proc/safety_clear_transit_dock(obj/docking_port/stationary/transit/T, obj/docking_port/mobile/M, list/returning)
+ M.setTimer(0)
+ var/error = M.initiate_docking(M.destination, M.preferred_direction)
+ if(!error)
+ returning += M
+ qdel(T, TRUE)
+
/datum/controller/subsystem/mapping/proc/add_nuke_threat(datum/nuke)
nuke_threats[nuke] = TRUE
check_nuke_threats()
@@ -108,16 +146,22 @@ SUBSYSTEM_DEF(mapping)
/datum/controller/subsystem/mapping/Recover()
flags |= SS_NO_INIT
+ initialized = SSmapping.initialized
map_templates = SSmapping.map_templates
ruins_templates = SSmapping.ruins_templates
space_ruins_templates = SSmapping.space_ruins_templates
lava_ruins_templates = SSmapping.lava_ruins_templates
shuttle_templates = SSmapping.shuttle_templates
shelter_templates = SSmapping.shelter_templates
+ unused_turfs = SSmapping.unused_turfs
+ turf_reservations = SSmapping.turf_reservations
+ used_turfs = SSmapping.used_turfs
config = SSmapping.config
next_map_config = SSmapping.next_map_config
+ clearing_reserved_turfs = SSmapping.clearing_reserved_turfs
+
z_list = SSmapping.z_list
#define INIT_ANNOUNCE(X) to_chat(world, "[X]"); log_world(X)
@@ -328,7 +372,6 @@ GLOBAL_LIST_EMPTY(the_station_areas)
shelter_templates[S.shelter_id] = S
map_templates[S.shelter_id] = S
-
//Manual loading of away missions.
/client/proc/admin_away()
set name = "Load Away Mission"
@@ -381,4 +424,58 @@ GLOBAL_LIST_EMPTY(the_station_areas)
break
//Link station gate with away gate and remove wait time.
GLOB.the_gateway.awaygate = new_gate
- GLOB.the_gateway.wait = world.time
\ No newline at end of file
+ GLOB.the_gateway.wait = world.time
+
+/datum/controller/subsystem/mapping/proc/RequestBlockReservation(width, height, z, type = /datum/turf_reservation, turf_type_override)
+ UNTIL(initialized && !clearing_reserved_turfs)
+ var/datum/turf_reservation/reserve = new type
+ if(turf_type_override)
+ reserve.turf_type = turf_type_override
+ if(!z)
+ for(var/i in levels_by_trait(ZTRAIT_RESERVED))
+ if(reserve.Reserve(width, height, i))
+ return reserve
+ else
+ if(!level_trait(z, ZTRAIT_RESERVED))
+ qdel(reserve)
+ return
+ else
+ if(reserve.Reserve(width, height, z))
+ return reserve
+ QDEL_NULL(reserve)
+
+//This is not for wiping reserved levels, use wipe_reservations() for that.
+/datum/controller/subsystem/mapping/proc/initialize_reserved_level()
+ UNTIL(!clearing_reserved_turfs) //regardless, lets add a check just in case.
+ clearing_reserved_turfs = TRUE //This operation will likely clear any existing reservations, so lets make sure nothing tries to make one while we're doing it.
+ for(var/i in levels_by_trait(ZTRAIT_RESERVED))
+ var/turf/A = get_turf(locate(SHUTTLE_TRANSIT_BORDER,SHUTTLE_TRANSIT_BORDER,i))
+ var/turf/B = get_turf(locate(world.maxx - SHUTTLE_TRANSIT_BORDER,world.maxy - SHUTTLE_TRANSIT_BORDER,i))
+ reserve_turfs(block(A, B))
+ 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
+ CHECK_TICK
+
+//DO NOT CALL THIS PROC DIRECTLY, CALL wipe_reservations().
+/datum/controller/subsystem/mapping/proc/do_wipe_turf_reservations()
+ UNTIL(initialized) //This proc is for AFTER init, before init turf reservations won't even exist and using this will likely break things.
+ for(var/i in turf_reservations)
+ var/datum/turf_reservation/TR = i
+ if(!QDELETED(TR))
+ qdel(TR, TRUE)
+ UNSETEMPTY(turf_reservations)
+ var/list/clearing = list()
+ for(var/l in unused_turfs) //unused_turfs is a assoc list by z = list(turfs)
+ if(islist(unused_turfs[l]))
+ clearing |= unused_turfs[l]
+ 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)
diff --git a/code/controllers/subsystem/shuttle.dm b/code/controllers/subsystem/shuttle.dm
index fe57bca354..d67ef40597 100644
--- a/code/controllers/subsystem/shuttle.dm
+++ b/code/controllers/subsystem/shuttle.dm
@@ -1,4 +1,3 @@
-#define HIGHLIGHT_DYNAMIC_TRANSIT 0
#define MAX_TRANSIT_REQUEST_RETRIES 10
SUBSYSTEM_DEF(shuttle)
@@ -14,10 +13,8 @@ SUBSYSTEM_DEF(shuttle)
var/list/stationary = list()
var/list/transit = list()
- var/list/turf/transit_turfs = list()
var/list/transit_requesters = list()
var/list/transit_request_failures = list()
- var/clear_transit = FALSE
//emergency shuttle stuff
var/obj/docking_port/mobile/emergency/emergency
@@ -67,15 +64,8 @@ SUBSYSTEM_DEF(shuttle)
continue
supply_packs[P.type] = P
- if(!transit_turfs.len)
- setup_transit_zone()
-
initial_load()
-#ifdef HIGHLIGHT_DYNAMIC_TRANSIT
- color_space()
-#endif
-
if(!arrivals)
WARNING("No /obj/docking_port/mobile/arrivals placed on the map!")
if(!emergency)
@@ -95,33 +85,6 @@ SUBSYSTEM_DEF(shuttle)
S.load_roundstart()
CHECK_TICK
-/datum/controller/subsystem/shuttle/proc/setup_transit_zone()
- // transit zone
- var/z = SSmapping.transit.z_value
- var/turf/A = get_turf(locate(SHUTTLE_TRANSIT_BORDER,SHUTTLE_TRANSIT_BORDER,z))
- var/turf/B = get_turf(locate(world.maxx - SHUTTLE_TRANSIT_BORDER,world.maxy - SHUTTLE_TRANSIT_BORDER,z))
- for(var/i in block(A, B))
- var/turf/T = i
- T.ChangeTurf(/turf/open/space)
- transit_turfs += T
- T.flags_1 |= UNUSED_TRANSIT_TURF_1
-
-#ifdef HIGHLIGHT_DYNAMIC_TRANSIT
-/datum/controller/subsystem/shuttle/proc/color_space()
- var/z = SSmapping.transit.z_value
- var/turf/A = get_turf(locate(SHUTTLE_TRANSIT_BORDER,SHUTTLE_TRANSIT_BORDER,z))
- var/turf/B = get_turf(locate(world.maxx - SHUTTLE_TRANSIT_BORDER,world.maxy - SHUTTLE_TRANSIT_BORDER,z))
- for(var/i in block(A, B))
- var/turf/T = i
- // Only dying the "pure" space, not the transit tiles
- if(istype(T, /turf/open/space/transit) || !isspaceturf(T))
- continue
- if((T.x == A.x) || (T.x == B.x) || (T.y == A.y) || (T.y == B.y))
- T.color = "#ffff00"
- else
- T.color = "#00ffff"
-#endif
-
/datum/controller/subsystem/shuttle/fire()
for(var/thing in mobile)
if(!thing)
@@ -129,12 +92,10 @@ SUBSYSTEM_DEF(shuttle)
continue
var/obj/docking_port/mobile/P = thing
P.check()
- var/changed_transit = FALSE
for(var/thing in transit)
var/obj/docking_port/stationary/transit/T = thing
if(!T.owner)
qdel(T, force=TRUE)
- changed_transit = TRUE
// This next one removes transit docks/zones that aren't
// immediately being used. This will mean that the zone creation
// code will be running a lot.
@@ -145,32 +106,21 @@ SUBSYSTEM_DEF(shuttle)
var/not_in_use = (!T.get_docked())
if(idle && not_centcom_evac && not_in_use)
qdel(T, force=TRUE)
- changed_transit = TRUE
- if(clear_transit)
- transit_requesters.Cut()
- for(var/i in transit)
- qdel(i, force=TRUE)
- setup_transit_zone()
- clear_transit = FALSE
- changed_transit = TRUE
-#ifdef HIGHLIGHT_DYNAMIC_TRANSIT
- if(changed_transit)
- color_space()
-#endif
CheckAutoEvac()
- while(transit_requesters.len)
- var/requester = popleft(transit_requesters)
- var/success = generate_transit_dock(requester)
- if(!success) // BACK OF THE QUEUE
- transit_request_failures[requester]++
- if(transit_request_failures[requester] < MAX_TRANSIT_REQUEST_RETRIES)
- transit_requesters += requester
- else
- var/obj/docking_port/mobile/M = requester
- M.transit_failure()
- if(MC_TICK_CHECK)
- break
+ if(!SSmapping.clearing_reserved_turfs)
+ while(transit_requesters.len)
+ var/requester = popleft(transit_requesters)
+ var/success = generate_transit_dock(requester)
+ if(!success) // BACK OF THE QUEUE
+ transit_request_failures[requester]++
+ if(transit_request_failures[requester] < MAX_TRANSIT_REQUEST_RETRIES)
+ transit_requesters += requester
+ else
+ var/obj/docking_port/mobile/M = requester
+ M.transit_failure()
+ if(MC_TICK_CHECK)
+ break
/datum/controller/subsystem/shuttle/proc/CheckAutoEvac()
if(emergencyNoEscape || emergencyNoRecall || !emergency || !SSticker.HasRoundStarted())
@@ -475,43 +425,29 @@ SUBSYSTEM_DEF(shuttle)
if(EAST, WEST)
transit_width += M.height
transit_height += M.width
+
/*
to_chat(world, "The attempted transit dock will be [transit_width] width, and \)
[transit_height] in height. The travel dir is [travel_dir]."
*/
- // Then find a place to put the zone
+ var/transit_path = /turf/open/space/transit
+ switch(travel_dir)
+ if(NORTH)
+ transit_path = /turf/open/space/transit/north
+ if(SOUTH)
+ transit_path = /turf/open/space/transit/south
+ if(EAST)
+ transit_path = /turf/open/space/transit/east
+ if(WEST)
+ transit_path = /turf/open/space/transit/west
- var/list/proposed_zone
+ var/datum/turf_reservation/proposal = SSmapping.RequestBlockReservation(transit_width, transit_height, null, /datum/turf_reservation/transit, transit_path)
- base:
- for(var/i in transit_turfs)
- CHECK_TICK
- var/turf/topleft = i
- if(!(topleft.flags_1 & UNUSED_TRANSIT_TURF_1))
- continue
- var/turf/bottomright = locate(topleft.x + transit_width,
- topleft.y + transit_height, topleft.z)
- if(!bottomright)
- continue
- if(!(bottomright.flags_1 & UNUSED_TRANSIT_TURF_1))
- continue
-
- proposed_zone = block(topleft, bottomright)
- if(!proposed_zone)
- continue
- for(var/j in proposed_zone)
- var/turf/T = j
- if(!T)
- continue base
- if(!(T.flags_1 & UNUSED_TRANSIT_TURF_1))
- continue base
- break base
-
- if((!proposed_zone) || (!proposed_zone.len))
+ if(!istype(proposal))
return FALSE
- var/turf/topleft = proposed_zone[1]
+ var/turf/bottomleft = locate(proposal.bottom_left_coords[1], proposal.bottom_left_coords[2], proposal.bottom_left_coords[3])
// Then create a transit docking port in the middle
var/coords = M.return_coords(0, 0, dock_dir)
/* 0------2
@@ -530,41 +466,24 @@ SUBSYSTEM_DEF(shuttle)
var/y2 = min(y0, y1)
// Then invert the numbers
- var/transit_x = topleft.x + SHUTTLE_TRANSIT_BORDER + abs(x2)
- var/transit_y = topleft.y + SHUTTLE_TRANSIT_BORDER + abs(y2)
+ var/transit_x = bottomleft.x + SHUTTLE_TRANSIT_BORDER + abs(x2)
+ var/transit_y = bottomleft.y + SHUTTLE_TRANSIT_BORDER + abs(y2)
- var/transit_path = /turf/open/space/transit
- switch(travel_dir)
- if(NORTH)
- transit_path = /turf/open/space/transit/north
- if(SOUTH)
- transit_path = /turf/open/space/transit/south
- if(EAST)
- transit_path = /turf/open/space/transit/east
- if(WEST)
- transit_path = /turf/open/space/transit/west
-
- var/turf/midpoint = locate(transit_x, transit_y, topleft.z)
+ var/turf/midpoint = locate(transit_x, transit_y, bottomleft.z)
if(!midpoint)
return FALSE
var/area/shuttle/transit/A = new()
A.parallax_movedir = travel_dir
- A.contents = proposed_zone
+ A.contents = proposal.reserved_turfs
var/obj/docking_port/stationary/transit/new_transit_dock = new(midpoint)
- new_transit_dock.assigned_turfs = proposed_zone
+ new_transit_dock.reserved_area = proposal
new_transit_dock.name = "Transit for [M.id]/[M.name]"
new_transit_dock.owner = M
new_transit_dock.assigned_area = A
-
// Add 180, because ports point inwards, rather than outwards
new_transit_dock.setDir(angle2dir(dock_angle))
- for(var/i in new_transit_dock.assigned_turfs)
- var/turf/T = i
- T.ChangeTurf(transit_path)
- T.flags_1 &= ~(UNUSED_TRANSIT_TURF_1)
-
M.assigned_transit = new_transit_dock
return new_transit_dock
@@ -575,9 +494,6 @@ SUBSYSTEM_DEF(shuttle)
stationary = SSshuttle.stationary
if (istype(SSshuttle.transit))
transit = SSshuttle.transit
-
- if (istype(SSshuttle.transit_turfs))
- transit_turfs = SSshuttle.transit_turfs
if (istype(SSshuttle.transit_requesters))
transit_requesters = SSshuttle.transit_requesters
if (istype(SSshuttle.transit_request_failures))
@@ -615,9 +531,6 @@ SUBSYSTEM_DEF(shuttle)
if (istype(SSshuttle.shuttle_purchase_requirements_met))
shuttle_purchase_requirements_met = SSshuttle.shuttle_purchase_requirements_met
- if (clear_transit)
- WARNING("The shuttle subsystem crashed and was recovered while clearing transit.")
-
centcom_message = SSshuttle.centcom_message
ordernum = SSshuttle.ordernum
points = SSshuttle.points
diff --git a/code/datums/components/stationloving.dm b/code/datums/components/stationloving.dm
index 2e1ee72a74..99e99f6465 100644
--- a/code/datums/components/stationloving.dm
+++ b/code/datums/components/stationloving.dm
@@ -59,7 +59,7 @@
return FALSE
if (is_station_level(T.z) || is_centcom_level(T.z))
return TRUE
- if (is_transit_level(T.z))
+ if (is_reserved_level(T.z))
if (is_type_in_typecache(A, allowed_shuttles))
return TRUE
diff --git a/code/game/area/areas/shuttles.dm b/code/game/area/areas/shuttles.dm
index 073e7714b2..90a6bbd3b6 100644
--- a/code/game/area/areas/shuttles.dm
+++ b/code/game/area/areas/shuttles.dm
@@ -67,6 +67,7 @@
/area/shuttle/transit
name = "Hyperspace"
desc = "Weeeeee"
+ dynamic_lighting = DYNAMIC_LIGHTING_DISABLED
/area/shuttle/custom
name = "Custom player shuttle"
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 95ca007031..f81da22d7f 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -112,7 +112,7 @@
if(!T)
return FALSE
- if(is_transit_level(T.z))
+ if(is_reserved_level(T.z))
for(var/A in SSshuttle.mobile)
var/obj/docking_port/mobile/M = A
if(M.launch_status == ENDGAME_TRANSIT)
diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm
index 61dc3ad919..445ed389b7 100755
--- a/code/game/machinery/computer/communications.dm
+++ b/code/game/machinery/computer/communications.dm
@@ -51,7 +51,7 @@
/obj/machinery/computer/communications/Topic(href, href_list)
if(..())
return
- if(!is_station_level(z) && !is_transit_level(z)) //Can only use in transit and on SS13
+ if(!is_station_level(z) && !is_reserved_level(z)) //Can only use in transit and on SS13
to_chat(usr, "Unable to establish a connection: \black You're too far away from the station!")
return
usr.set_machine(src)
diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm
index e6ddd72e3a..d34e1ebd42 100644
--- a/code/modules/admin/verbs/debug.dm
+++ b/code/modules/admin/verbs/debug.dm
@@ -961,15 +961,17 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
/client/proc/clear_dynamic_transit()
set category = "Debug"
- set name = "Clear Dynamic Transit"
- set desc = "Deallocates all transit space, restoring it to round start conditions."
+ set name = "Clear Dynamic Turf Reservations"
+ set desc = "Deallocates all reserved space, restoring it to round start conditions."
if(!holder)
return
- SSshuttle.clear_transit = TRUE
+ var/answer = alert("WARNING: THIS WILL WIPE ALL RESERVED SPACE TO A CLEAN SLATE! ANY MOVING SHUTTLES, ELEVATORS, OR IN-PROGRESS PHOTOGRAPHY WILL BE DELETED!", "Really wipe dynamic turfs?", "YES", "NO")
+ if(answer != "YES")
+ return
message_admins("[key_name_admin(src)] cleared dynamic transit space.")
SSblackbox.record_feedback("tally", "admin_verb", 1, "Clear Dynamic Transit") // If...
log_admin("[key_name(src)] cleared dynamic transit space.")
-
+ SSmapping.wipe_reservations() //this goes after it's logged, incase something horrible happens.
/client/proc/toggle_medal_disable()
set category = "Debug"
diff --git a/code/modules/antagonists/nukeop/nukeop.dm b/code/modules/antagonists/nukeop/nukeop.dm
index 1796227f9c..3df9d1d9ca 100644
--- a/code/modules/antagonists/nukeop/nukeop.dm
+++ b/code/modules/antagonists/nukeop/nukeop.dm
@@ -258,7 +258,8 @@
/datum/team/nuclear/proc/syndies_escaped()
var/obj/docking_port/mobile/S = SSshuttle.getShuttle("syndicate")
- return S && (is_centcom_level(S.z) || is_transit_level(S.z))
+ var/obj/docking_port/stationary/transit/T = locate() in S.loc
+ return S && (is_centcom_level(S.z) || T)
/datum/team/nuclear/proc/get_result()
var/evacuation = SSshuttle.emergency.mode == SHUTTLE_ENDGAME
diff --git a/code/modules/events/pirates.dm b/code/modules/events/pirates.dm
index 8a9df2f58f..8b904ae9b8 100644
--- a/code/modules/events/pirates.dm
+++ b/code/modules/events/pirates.dm
@@ -209,7 +209,7 @@
/obj/docking_port/mobile/pirate/initiate_docking(obj/docking_port/stationary/new_dock, movement_direction, force=FALSE)
. = ..()
- if(. == DOCKING_SUCCESS && !is_transit_level(new_dock.z))
+ if(. == DOCKING_SUCCESS && !is_reserved_level(new_dock.z))
engines_cooling = TRUE
addtimer(CALLBACK(src,.proc/reset_cooldown),engine_cooldown,TIMER_UNIQUE)
diff --git a/code/modules/mapping/space_management/space_reservation.dm b/code/modules/mapping/space_management/space_reservation.dm
new file mode 100644
index 0000000000..38e7e4ecad
--- /dev/null
+++ b/code/modules/mapping/space_management/space_reservation.dm
@@ -0,0 +1,70 @@
+
+//Yes, they can only be rectangular.
+//Yes, I'm sorry.
+/datum/turf_reservation
+ var/list/reserved_turfs = list()
+ var/bottom_left_coords[3]
+ var/top_right_coords[3]
+ var/wipe_reservation_on_release = TRUE
+ var/turf_type = /turf/open/space
+
+/datum/turf_reservation/transit
+ 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)
+
+/datum/turf_reservation/proc/Reserve(width, height, zlevel)
+ if(width > world.maxx || height > world.maxy)
+ return FALSE
+ var/list/avail = SSmapping.unused_turfs["[zlevel]"]
+ var/turf/BL
+ var/turf/TR
+ var/list/turf/final = list()
+ var/passing = FALSE
+ for(var/i in avail)
+ CHECK_TICK
+ BL = i
+ if(!(BL.flags_1 & UNUSED_RESERVATION_TURF_1))
+ continue
+ if(BL.x + width > world.maxx || BL.y + height > world.maxy)
+ continue
+ TR = locate(BL.x + width, BL.y + height, BL.z)
+ if(!(TR.flags_1 & UNUSED_RESERVATION_TURF_1))
+ continue
+ final = block(BL, TR)
+ if(!final)
+ continue
+ passing = TRUE
+ for(var/I in final)
+ var/turf/checking = I
+ if(!(checking.flags_1 & UNUSED_RESERVATION_TURF_1))
+ passing = FALSE
+ break
+ if(!passing)
+ continue
+ break
+ if(!passing || !istype(BL) || !istype(TR))
+ return FALSE
+ bottom_left_coords = list(BL.x, BL.y, BL.z)
+ top_right_coords = list(TR.x, TR.y, TR.z)
+ for(var/i in final)
+ var/turf/T = i
+ reserved_turfs |= T
+ T.flags_1 &= ~UNUSED_RESERVATION_TURF_1
+ SSmapping.unused_turfs["[T.z]"] -= T
+ SSmapping.used_turfs[T] = src
+ T.ChangeTurf(turf_type, turf_type)
+ return TRUE
+
+/datum/turf_reservation/New()
+ LAZYADD(SSmapping.turf_reservations, src)
+
+/datum/turf_reservation/Destroy()
+ Release()
+ LAZYREMOVE(SSmapping.turf_reservations, src)
+ return ..()
diff --git a/code/modules/mining/equipment/wormhole_jaunter.dm b/code/modules/mining/equipment/wormhole_jaunter.dm
index 437d6fb26f..9cb3f5c323 100644
--- a/code/modules/mining/equipment/wormhole_jaunter.dm
+++ b/code/modules/mining/equipment/wormhole_jaunter.dm
@@ -20,7 +20,7 @@
/obj/item/wormhole_jaunter/proc/turf_check(mob/user)
var/turf/device_turf = get_turf(user)
- if(!device_turf || is_centcom_level(device_turf.z) || is_transit_level(device_turf.z))
+ if(!device_turf || is_centcom_level(device_turf.z) || is_reserved_level(device_turf.z))
to_chat(user, "You're having difficulties getting the [src.name] to work.")
return FALSE
return TRUE
diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm
index 17476c1618..bcb186a776 100644
--- a/code/modules/mining/lavaland/necropolis_chests.dm
+++ b/code/modules/mining/lavaland/necropolis_chests.dm
@@ -595,7 +595,7 @@
to_chat(user, "You unfold the ladder. It extends much farther than you were expecting.")
var/last_ladder = null
for(var/i in 1 to world.maxz)
- if(is_centcom_level(i) || is_transit_level(i) || is_reebe(i) || is_away_level(i))
+ if(is_centcom_level(i) || is_reserved_level(i) || is_reebe(i) || is_away_level(i))
continue
var/turf/T2 = locate(ladder_x, ladder_y, i)
last_ladder = new /obj/structure/ladder/unbreakable/jacob(T2, null, last_ladder)
diff --git a/code/modules/shuttle/docking.dm b/code/modules/shuttle/docking.dm
index c0052845c7..fa78c8cb99 100644
--- a/code/modules/shuttle/docking.dm
+++ b/code/modules/shuttle/docking.dm
@@ -16,7 +16,7 @@
// The area that gets placed under where the shuttle moved from
var/underlying_area_type = SHUTTLE_DEFAULT_UNDERLYING_AREA
-
+
if(old_dock) //Dock overwrites
underlying_area_type = old_dock.area_type
@@ -105,7 +105,7 @@
list/areas_to_move,
rotation,
)
-
+
for(var/i in 1 to old_turfs.len)
CHECK_TICK
var/turf/oldT = old_turfs[i]
@@ -173,7 +173,7 @@
movement_direction,
area/underlying_old_area,
)
-
+
underlying_old_area.afterShuttleMove()
// Parallax handling
diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm
index 363b4408b2..92fb95c00e 100644
--- a/code/modules/shuttle/shuttle.dm
+++ b/code/modules/shuttle/shuttle.dm
@@ -202,7 +202,7 @@
/obj/docking_port/stationary/transit
name = "In Transit"
- var/list/turf/assigned_turfs = list()
+ var/datum/turf_reservation/reserved_area
var/area/shuttle/transit/assigned_area
var/obj/docking_port/mobile/owner
@@ -210,14 +210,6 @@
. = ..()
SSshuttle.transit += src
-/obj/docking_port/stationary/transit/proc/dezone()
- for(var/i in 1 to assigned_turfs.len)
- var/turf/T = assigned_turfs[i]
- if(istype(T, /turf/open/space/transit))
- T.ChangeTurf(/turf/open/space)
- T.assemble_baseturfs(initial(T.baseturfs))
- T.flags_1 |= UNUSED_TRANSIT_TURF_1
-
/obj/docking_port/stationary/transit/Destroy(force=FALSE)
if(force)
if(get_docked())
@@ -227,11 +219,10 @@
if(owner.assigned_transit == src)
owner.assigned_transit = null
owner = null
- if(assigned_turfs)
- dezone()
- assigned_turfs.Cut()
- assigned_turfs = null
- . = ..()
+ if(!QDELETED(reserved_area))
+ qdel(reserved_area)
+ reserved_area = null
+ return ..()
/obj/docking_port/mobile
name = "shuttle"
@@ -282,7 +273,7 @@
SSshuttle.mobile -= src
destination = null
previous = null
- assigned_transit = null
+ QDEL_NULL(assigned_transit) //don't need it where we're goin'!
shuttle_areas = null
remove_ripples()
. = ..()
@@ -433,7 +424,7 @@
underlying_area_type = current_dock.area_type
var/list/old_turfs = return_ordered_turfs(x, y, z, dir)
-
+
var/area/underlying_area
for(var/i in GLOB.sortedAreas)
var/area/place = i
@@ -451,7 +442,7 @@
underlying_area.contents += oldT
oldT.change_area(old_area, underlying_area)
oldT.empty(FALSE)
-
+
// Here we locate the bottomost shuttle boundary and remove all turfs above it
var/list/baseturf_cache = oldT.baseturfs
for(var/k in 1 to length(baseturf_cache))
diff --git a/tgstation.dme b/tgstation.dme
index 527db71b8c..39ecf1a066 100755
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -1752,6 +1752,7 @@
#include "code\modules\mapping\reader.dm"
#include "code\modules\mapping\ruins.dm"
#include "code\modules\mapping\space_management\space_level.dm"
+#include "code\modules\mapping\space_management\space_reservation.dm"
#include "code\modules\mapping\space_management\space_transition.dm"
#include "code\modules\mapping\space_management\traits.dm"
#include "code\modules\mapping\space_management\zlevel_manager.dm"