diff --git a/code/ZAS/Connection.dm b/code/ZAS/Connection.dm
index b26217eeb6..70b7f70e63 100644
--- a/code/ZAS/Connection.dm
+++ b/code/ZAS/Connection.dm
@@ -13,68 +13,62 @@ Indirect connections will not merge the two zones after they reach equilibrium.
var/zone/zone_A
var/zone/zone_B
- var/ref_A
- var/ref_B
-
var/indirect = CONNECTION_DIRECT //If the connection is purely indirect, the zones should not join.
- var/last_updated //The tick at which this was last updated.
-
- var/no_zone_count = 0
-
-
/connection/New(turf/T,turf/O)
+ . = ..()
+
A = T
B = O
+
if(A.zone && B.zone)
- if(!A.zone.connections) A.zone.connections = list()
+ if(!A.zone.connections)
+ A.zone.connections = list()
A.zone.connections += src
zone_A = A.zone
- ref_A = "\ref[A]"
- if(!B.zone.connections) B.zone.connections = list()
+ if(!B.zone.connections)
+ B.zone.connections = list()
B.zone.connections += src
zone_B = B.zone
- ref_B = "\ref[B]"
- if(ref_A in air_master.turfs_with_connections)
- var/list/connections = air_master.turfs_with_connections[ref_A]
+ if(A in air_master.turfs_with_connections)
+ var/list/connections = air_master.turfs_with_connections[A]
connections.Add(src)
else
- air_master.turfs_with_connections[ref_A] = list(src)
+ air_master.turfs_with_connections[A] = list(src)
- if(ref_B in air_master.turfs_with_connections)
- var/list/connections = air_master.turfs_with_connections[ref_B]
+ if(B in air_master.turfs_with_connections)
+ var/list/connections = air_master.turfs_with_connections[B]
connections.Add(src)
else
- air_master.turfs_with_connections[ref_B] = list(src)
+ air_master.turfs_with_connections[B] = list(src)
if(A.CanPass(null, B, 0, 0))
- ConnectZones(A.zone, B.zone, 1)
-
- if(A.HasDoor(B) || B.HasDoor(A))
+ if(!A.CanPass(null, B, 1.5, 1))
indirect = CONNECTION_INDIRECT
+ ConnectZones(A.zone, B.zone, indirect)
+
else
ConnectZones(A.zone, B.zone)
indirect = CONNECTION_CLOSED
-
else
world.log << "Attempted to create connection object for non-zone tiles: [T] ([T.x],[T.y],[T.z]) -> [O] ([O.x],[O.y],[O.z])"
- del(src)
+ SoftDelete()
/connection/Del()
//remove connections from master lists.
- if(ref_B in air_master.turfs_with_connections)
- var/list/connections = air_master.turfs_with_connections[ref_B]
+ if(B in air_master.turfs_with_connections)
+ var/list/connections = air_master.turfs_with_connections[B]
connections.Remove(src)
- if(ref_A in air_master.turfs_with_connections)
- var/list/connections = air_master.turfs_with_connections[ref_A]
+ if(A in air_master.turfs_with_connections)
+ var/list/connections = air_master.turfs_with_connections[A]
connections.Remove(src)
//Remove connection from zones.
@@ -110,6 +104,46 @@ Indirect connections will not merge the two zones after they reach equilibrium.
. = ..()
+/connection/proc/SoftDelete()
+ //remove connections from master lists.
+ if(B in air_master.turfs_with_connections)
+ var/list/connections = air_master.turfs_with_connections[B]
+ connections.Remove(src)
+
+ if(A in air_master.turfs_with_connections)
+ var/list/connections = air_master.turfs_with_connections[A]
+ connections.Remove(src)
+
+ //Remove connection from zones.
+ if(A)
+ if(A.zone && A.zone.connections)
+ A.zone.connections.Remove(src)
+ if(!A.zone.connections.len)
+ A.zone.connections = null
+
+ if(istype(zone_A) && (!A || A.zone != zone_A))
+ if(zone_A.connections)
+ zone_A.connections.Remove(src)
+ if(!zone_A.connections.len)
+ zone_A.connections = null
+
+ if(B)
+ if(B.zone && B.zone.connections)
+ B.zone.connections.Remove(src)
+ if(!B.zone.connections.len)
+ B.zone.connections = null
+
+ if(istype(zone_B) && (!B || B.zone != zone_B))
+ if(zone_B.connections)
+ zone_B.connections.Remove(src)
+ if(!zone_B.connections.len)
+ zone_B.connections = null
+
+ //Disconnect zones while handling unusual conditions.
+ // e.g. loss of a zone on a turf
+ DisconnectZones(zone_A, zone_B)
+
+
/connection/proc/ConnectZones(var/zone/zone_1, var/zone/zone_2, open = 0)
//Sanity checking
@@ -139,6 +173,18 @@ Indirect connections will not merge the two zones after they reach equilibrium.
zone_2.connected_zones += zone_1
zone_2.connected_zones[zone_1] = 1
+ if(open == CONNECTION_DIRECT)
+ if(!zone_1.direct_connections)
+ zone_1.direct_connections = list(src)
+ else
+ zone_1.direct_connections += src
+
+ if(!zone_2.direct_connections)
+ zone_2.direct_connections = list(src)
+ else
+ zone_2.direct_connections += src
+
+
//Handle closed connections.
else
@@ -192,6 +238,15 @@ Indirect connections will not merge the two zones after they reach equilibrium.
if(!zone_2.connected_zones.len)
zone_2.connected_zones = null
+ if(indirect == CONNECTION_DIRECT)
+ zone_1.direct_connections -= src
+ if(!zone_1.direct_connections.len)
+ zone_1.direct_connections = null
+
+ zone_2.direct_connections -= src
+ if(!zone_2.direct_connections.len)
+ zone_2.direct_connections = null
+
else
//Handle disconnection of closed zones.
if( (zone_1 in zone_2.closed_connection_zones) || (zone_2 in zone_1.closed_connection_zones) )
@@ -221,35 +276,23 @@ Indirect connections will not merge the two zones after they reach equilibrium.
//Check sanity: existance of turfs
if(!A || !B)
- del src
+ SoftDelete()
+ return
+
+ //Check sanity: loss of zone
+ if(!A.zone || !B.zone)
+ SoftDelete()
+ return
//Check sanity: zones are different
if(A.zone == B.zone)
- del src
-
- //Check sanity: same turfs as before.
- if(ref_A != "\ref[A]" || ref_B != "\ref[B]")
- del src
+ SoftDelete()
+ return
//Handle zones changing on a turf.
if((A.zone && A.zone != zone_A) || (B.zone && B.zone != zone_B))
Sanitize()
- //Manage sudden loss of a turfs zone. (e.g. a wall being built)
- if(!A.zone || !B.zone)
- no_zone_count++
- if(no_zone_count >= 5)
- //world.log << "Connection removed: [A] or [B] missing a zone."
- del src
- return 0
-
- return 1
-
-
-/connection/proc/CheckPassSanity()
- //Sanity check, first.
- Cleanup()
-
if(A.zone && B.zone)
//If no walls are blocking us...
@@ -262,7 +305,7 @@ Indirect connections will not merge the two zones after they reach equilibrium.
//Make and remove connections to let air pass.
if(indirect == CONNECTION_CLOSED)
DisconnectZones(A.zone, B.zone)
- ConnectZones(A.zone, B.zone, 1)
+ ConnectZones(A.zone, B.zone, door_pass + 1)
if(door_pass)
indirect = CONNECTION_DIRECT
@@ -277,7 +320,8 @@ Indirect connections will not merge the two zones after they reach equilibrium.
//If I can no longer pass air, better delete
else
- del src
+ SoftDelete()
+ return
/connection/proc/Sanitize()
//If the zones change on connected turfs, update it.
@@ -293,9 +337,6 @@ Indirect connections will not merge the two zones after they reach equilibrium.
A = temp
zone_B = B.zone
zone_A = A.zone
- var/temp_ref = ref_A
- ref_A = ref_B
- ref_B = temp_ref
return
//Handle removal of connections from archived zones.
diff --git a/code/ZAS/Debug.dm b/code/ZAS/Debug.dm
index 6586cbaaec..762843d5b1 100644
--- a/code/ZAS/Debug.dm
+++ b/code/ZAS/Debug.dm
@@ -1,3 +1,14 @@
+client/proc/ZoneTick()
+ set category = "Debug"
+ set name = "Process Atmos"
+
+ var/result = air_master.Tick()
+ if(result)
+ src << "Sucessfully Processed."
+
+ else
+ src << "Failed to process! ([air_master.tick_progress])"
+
client/proc/Zone_Info(turf/T as null|turf)
set category = "Debug"
@@ -120,3 +131,82 @@ zone/proc/DebugDisplay(client/client)
var/turf/zloc = pick(Z.contents)
client << "\red Illegal air datum shared by: [zloc.loc.name]"
+
+client/proc/TestZASRebuild()
+// var/turf/turf = get_turf(mob)
+ var/zone/current_zone = mob.loc:zone
+ if(!current_zone)
+ src << "There is no zone there!"
+ return
+
+ var/list/current_adjacents = list()
+ var/list/overlays = list()
+ var/adjacent_id
+ var/lowest_id
+
+ var/list/identical_ids = list()
+ var/list/turfs = current_zone.contents.Copy()
+ var/current_identifier = 1
+
+ for(var/turf/simulated/current in turfs)
+ lowest_id = null
+ current_adjacents = list()
+
+ for(var/direction in cardinal)
+ var/turf/simulated/adjacent = get_step(current, direction)
+ if(!current.ZAirPass(adjacent))
+ continue
+ if(turfs.Find(adjacent))
+ current_adjacents += adjacent
+ adjacent_id = turfs[adjacent]
+
+ if(adjacent_id && (!lowest_id || adjacent_id < lowest_id))
+ lowest_id = adjacent_id
+
+ if(!lowest_id)
+ lowest_id = current_identifier++
+ identical_ids += lowest_id
+ overlays += image('icons/misc/debug_rebuild.dmi',, "[lowest_id]")
+
+ for(var/turf/simulated/adjacent in current_adjacents)
+ adjacent_id = turfs[adjacent]
+ if(adjacent_id != lowest_id)
+ if(adjacent_id)
+ adjacent.overlays -= overlays[adjacent_id]
+ identical_ids[adjacent_id] = lowest_id
+
+ turfs[adjacent] = lowest_id
+ adjacent.overlays += overlays[lowest_id]
+
+ sleep(5)
+
+ if(turfs[current])
+ current.overlays += overlays[turfs[current]]
+ turfs[current] = lowest_id
+ current.overlays += overlays[lowest_id]
+ sleep(5)
+
+ var/list/final_arrangement = list()
+
+ for(var/turf/simulated/current in turfs)
+ current_identifier = identical_ids[turfs[current]]
+ current.overlays -= overlays[turfs[current]]
+ current.overlays += overlays[current_identifier]
+ sleep(5)
+
+ if( current_identifier > final_arrangement.len )
+ final_arrangement.len = current_identifier
+ final_arrangement[current_identifier] = list(current)
+
+ else
+ final_arrangement[current_identifier] += current
+
+ //lazy but fast
+ final_arrangement.Remove(null)
+
+ src << "There are [final_arrangement.len] unique segments."
+
+ for(var/turf/current in turfs)
+ current.overlays -= overlays
+
+ return final_arrangement
diff --git a/code/ZAS/FEA_gas_mixture.dm b/code/ZAS/FEA_gas_mixture.dm
index 273d7669f1..58ee345a03 100644
--- a/code/ZAS/FEA_gas_mixture.dm
+++ b/code/ZAS/FEA_gas_mixture.dm
@@ -8,7 +8,7 @@ What are the archived variables for?
#define SPECIFIC_HEAT_AIR 20
#define SPECIFIC_HEAT_CDO 30
#define HEAT_CAPACITY_CALCULATION(oxygen,carbon_dioxide,nitrogen,toxins) \
- (carbon_dioxide*SPECIFIC_HEAT_CDO + (oxygen+nitrogen)*SPECIFIC_HEAT_AIR + toxins*SPECIFIC_HEAT_TOXIN)
+ max(0, carbon_dioxide * SPECIFIC_HEAT_CDO + (oxygen + nitrogen) * SPECIFIC_HEAT_AIR + toxins * SPECIFIC_HEAT_TOXIN)
#define MINIMUM_HEAT_CAPACITY 0.0003
#define QUANTIZE(variable) (round(variable,0.0001))
diff --git a/code/ZAS/FEA_system.dm b/code/ZAS/FEA_system.dm
index c2a33ad99d..508cbb0125 100644
--- a/code/ZAS/FEA_system.dm
+++ b/code/ZAS/FEA_system.dm
@@ -53,7 +53,6 @@ Important Procedures
*/
-var/kill_air = 0
var/tick_multiplier = 2
atom/proc/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0)
@@ -87,17 +86,24 @@ atom/proc/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0)
var/datum/controller/air_system/air_master
-/datum/controller/air_system/
- //Geoemetry lists
+/datum/controller/air_system
+ //Geometry lists
var/list/turfs_with_connections = list()
var/list/active_hotspots = list()
//Special functions lists
+ var/reconsidering_zones = FALSE
var/list/tiles_to_reconsider_zones = list()
+ var/list/tiles_to_reconsider_alternate
//Geometry updates lists
+ var/updating_tiles = FALSE
var/list/tiles_to_update = list()
+ var/list/tiles_to_update_alternate
+
+ var/checking_connections = FALSE
var/list/connections_to_check = list()
+ var/list/connections_to_check_alternate
var/current_cycle = 0
var/update_delay = 5 //How long between check should it try to process atmos again.
@@ -106,20 +112,7 @@ var/datum/controller/air_system/air_master
var/tick_progress = 0
-/* process()
- //Call this to process air movements for a cycle
-
- process_rebuild_select_groups()
- //Used by process()
- //Warning: Do not call this
-
- rebuild_group(datum/air_group)
- //Used by process_rebuild_select_groups()
- //Warning: Do not call this, add the group to air_master.groups_to_rebuild instead
- */
-
-
-/datum/controller/air_system/proc/setup()
+/datum/controller/air_system/proc/Setup()
//Purpose: Call this at the start to setup air groups geometry
// (Warning: Very processor intensive but only must be done once per round)
//Called by: Gameticker/Master controller
@@ -147,10 +140,11 @@ var/datum/controller/air_system/air_master
Total Simulated Turfs: [simulated_turf_count]
Total Zones: [zones.len]
Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_count]"}
- /*
- spawn start()
-/datum/controller/air_system/proc/start()
+// spawn Start()
+
+
+/datum/controller/air_system/proc/Start()
//Purpose: This is kicked off by the master controller, and controls the processing of all atmosphere.
//Called by: Master controller
//Inputs: None.
@@ -160,45 +154,60 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun
set background = 1
while(1)
- if(!kill_air)
- current_cycle++
- var/success = tick() //Changed so that a runtime does not crash the ticker.
+ if(!air_processing_killed)
+ var/success = Tick() //Changed so that a runtime does not crash the ticker.
if(!success) //Runtimed.
failed_ticks++
if(failed_ticks > 20)
world << "ERROR IN ATMOS TICKER. Killing air simulation!"
- kill_air = 1
+ air_processing_killed = 1
sleep(max(5,update_delay*tick_multiplier))
- */
-/datum/controller/air_system/proc/tick()
+
+/datum/controller/air_system/proc/Tick()
. = 1 //Set the default return value, for runtime detection.
+ current_cycle++
+
+ //If there are tiles to update, do so.
tick_progress = "update_air_properties"
- if(tiles_to_update.len) //If there are tiles to update, do so.
+ if(tiles_to_update.len)
+ updating_tiles = TRUE
+
for(var/turf/simulated/T in tiles_to_update)
if(. && T && !T.update_air_properties())
- . = 0 //If a runtime occured, make sure we can sense it.
- //message_admins("ZASALERT: Unable run turf/simualted/update_air_properties()")
+ //If a runtime occured, make sure we can sense it.
+ . = 0
+
+ updating_tiles = FALSE
+
if(.)
- tiles_to_update = list()
+ if(tiles_to_update_alternate)
+ tiles_to_update = tiles_to_update_alternate
+ tiles_to_update_alternate = null
+ else
+ tiles_to_update = list()
+
+ else if(tiles_to_update_alternate)
+ tiles_to_update |= tiles_to_update_alternate
+ tiles_to_update_alternate = null
//Check sanity on connection objects.
if(.)
tick_progress = "connections_to_check"
if(connections_to_check.len)
- for(var/connection/C in connections_to_check)
- C.CheckPassSanity()
- connections_to_check = list()
+ checking_connections = TRUE
- //Ensure tiles still have zones.
- if(.)
- tick_progress = "tiles_to_reconsider_zones"
- if(tiles_to_reconsider_zones.len)
- for(var/turf/simulated/T in tiles_to_reconsider_zones)
- if(!T.zone)
- new /zone(T)
- tiles_to_reconsider_zones = list()
+ for(var/connection/C in connections_to_check)
+ C.Cleanup()
+
+ checking_connections = FALSE
+
+ if(connections_to_check_alternate)
+ connections_to_check = connections_to_check_alternate
+ connections_to_check_alternate = null
+ else
+ connections_to_check = list()
//Process zones.
if(.)
@@ -210,6 +219,25 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun
Z.last_update = current_cycle
if(. && Z && !output)
. = 0
+
+ //Ensure tiles still have zones.
+ if(.)
+ tick_progress = "tiles_to_reconsider_zones"
+ if(tiles_to_reconsider_zones.len)
+ reconsidering_zones = TRUE
+
+ for(var/turf/simulated/T in tiles_to_reconsider_zones)
+ if(!T.zone)
+ new /zone(T)
+
+ reconsidering_zones = FALSE
+
+ if(tiles_to_reconsider_alternate)
+ tiles_to_reconsider_zones = tiles_to_reconsider_alternate
+ tiles_to_reconsider_alternate = null
+ else
+ tiles_to_reconsider_zones = list()
+
//Process fires.
if(.)
tick_progress = "active_hotspots (fire)"
@@ -218,4 +246,54 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun
. = 0
if(.)
- tick_progress = "success"
\ No newline at end of file
+ tick_progress = "success"
+
+
+/datum/controller/air_system/proc/AddTurfToUpdate(turf/simulated/outdated_turf)
+ var/list/tiles_to_check = list()
+
+ if(istype(outdated_turf))
+ tiles_to_check |= outdated_turf
+
+ if(istype(outdated_turf, /turf))
+ for(var/direction in cardinal)
+ var/turf/simulated/adjacent_turf = get_step(outdated_turf, direction)
+ if(istype(adjacent_turf))
+ tiles_to_check |= adjacent_turf
+
+ if(updating_tiles)
+ if(!tiles_to_update_alternate)
+ tiles_to_update_alternate = tiles_to_check
+ else
+ tiles_to_update_alternate |= tiles_to_check
+ else
+ tiles_to_update |= tiles_to_check
+
+
+/datum/controller/air_system/proc/AddConnectionToCheck(connection/connection)
+ if(checking_connections)
+ if(istype(connection, /list))
+ if(!connections_to_check_alternate)
+ connections_to_check_alternate = connection
+
+ else if(!connections_to_check_alternate)
+ connections_to_check_alternate = list()
+
+ connections_to_check_alternate |= connection
+
+ else
+ connections_to_check |= connection
+
+
+/datum/controller/air_system/proc/ReconsiderTileZone(var/turf/simulated/zoneless_turf)
+ if(zoneless_turf.zone)
+ return
+
+ if(reconsidering_zones)
+ if(!tiles_to_reconsider_alternate)
+ tiles_to_reconsider_alternate = list()
+
+ tiles_to_reconsider_alternate |= zoneless_turf
+
+ else
+ tiles_to_reconsider_zones |= zoneless_turf
diff --git a/code/ZAS/Functions.dm b/code/ZAS/Functions.dm
index ce24513418..4a1ffaaea2 100644
--- a/code/ZAS/Functions.dm
+++ b/code/ZAS/Functions.dm
@@ -157,14 +157,13 @@ proc/ZConnect(turf/simulated/A,turf/simulated/B)
if(!A.zone || !B.zone) return
if(A.zone == B.zone) return
- if(A.CanPass(null,B,0,1))
+ if(A.CanPass(null, B, 1.5, 1) && A.zone.air.compare(B.zone.air))
return ZMerge(A.zone,B.zone)
//Ensure the connection isn't already made.
- if("\ref[A]" in air_master.turfs_with_connections)
- for(var/connection/C in air_master.turfs_with_connections["\ref[A]"])
- C.Cleanup()
- if(C && (C.B == B || C.A == B))
+ if(A in air_master.turfs_with_connections)
+ for(var/connection/C in air_master.turfs_with_connections[A])
+ if(C.B == B || C.A == B)
return
//Make the connection.
diff --git a/code/ZAS/ZAS_Turfs.dm b/code/ZAS/ZAS_Turfs.dm
index 0d4f0496b1..d376d927f5 100644
--- a/code/ZAS/ZAS_Turfs.dm
+++ b/code/ZAS/ZAS_Turfs.dm
@@ -136,8 +136,8 @@
if(!zone && !blocks_air) //No zone, but not a wall.
for(var/direction in DoorDirections) //Check door directions first.
- if(air_check_directions&direction)
- var/turf/simulated/T = get_step(src,direction)
+ if(air_check_directions & direction)
+ var/turf/simulated/T = get_step(src, direction)
if(!istype(T))
continue
if(T.zone)
@@ -145,7 +145,7 @@
break
if(!zone) //Still no zone
for(var/direction in CounterDoorDirections) //Check the others second.
- if(air_check_directions&direction)
+ if(air_check_directions & direction)
var/turf/simulated/T = get_step(src,direction)
if(!istype(T))
continue
@@ -158,77 +158,23 @@
new/zone(list(src))
//Check pass sanity of the connections.
- if("\ref[src]" in air_master.turfs_with_connections)
- for(var/connection/C in air_master.turfs_with_connections["\ref[src]"])
- air_master.connections_to_check |= C
+ if(src in air_master.turfs_with_connections)
+ air_master.AddConnectionToCheck(air_master.turfs_with_connections[src])
+
+ if(zone && CanPass(null, src, 0, 0))
- if(zone && !zone.rebuild)
for(var/direction in cardinal)
var/turf/T = get_step(src,direction)
if(!istype(T))
continue
//I can connect to air in this direction
- if(air_check_directions&direction)
+ if(air_check_directions & direction && !(air_directions_archived & direction))
- //If either block air, we must look to see if the adjacent turfs need rebuilt.
- if(!CanPass(null, T, 0, 0))
-
- //Target blocks air
- if(!T.CanPass(null, T, 0, 0))
- var/turf/NT = get_step(T, direction)
-
- //If that turf is in my zone still, rebuild.
- if(istype(NT,/turf/simulated) && NT in zone.contents)
- zone.rebuild = 1
-
- //If that is an unsimulated tile in my zone, see if we need to rebuild or just remove.
- else if(istype(NT) && NT in zone.unsimulated_tiles)
- var/consider_rebuild = 0
- for(var/d in cardinal)
- var/turf/UT = get_step(NT,d)
- if(istype(UT, /turf/simulated) && UT.zone == zone && UT.CanPass(null, NT, 0, 0)) //If we find a neighboring tile that is in the same zone, check if we need to rebuild
- consider_rebuild = 1
- break
- if(consider_rebuild)
- zone.rebuild = 1 //Gotta check if we need to rebuild, dammit
- else
- zone.RemoveTurf(NT) //Not adjacent to anything, and unsimulated. Goodbye~
-
- //To make a closed connection through closed door.
- ZConnect(T, src)
-
- //If I block air.
- else if(T.zone && !T.zone.rebuild)
- var/turf/NT = get_step(src, reverse_direction(direction))
-
- //If I am splitting a zone, rebuild.
- if(istype(NT,/turf/simulated) && (NT in T.zone.contents || (NT.zone && T in NT.zone.contents)))
- T.zone.rebuild = 1
-
- //If NT is unsimulated, parse if I should remove it or rebuild.
- else if(istype(NT) && NT in T.zone.unsimulated_tiles)
- var/consider_rebuild = 0
- for(var/d in cardinal)
- var/turf/UT = get_step(NT,d)
- if(istype(UT, /turf/simulated) && UT.zone == T.zone && UT.CanPass(null, NT, 0, 0)) //If we find a neighboring tile that is in the same zone, check if we need to rebuild
- consider_rebuild = 1
- break
-
- //Needs rebuilt.
- if(consider_rebuild)
- T.zone.rebuild = 1
-
- //Not adjacent to anything, and unsimulated. Goodbye~
- else
- T.zone.RemoveTurf(NT)
-
- else
- //Produce connection through open door.
- ZConnect(src,T)
+ ZConnect(src,T)
//Something like a wall was built, changing the geometry.
- else if(air_directions_archived&direction)
+ else if(!(air_check_directions & direction) && air_directions_archived & direction)
var/turf/NT = get_step(T, direction)
//If the tile is in our own zone, and we cannot connect to it, better rebuild.
@@ -290,13 +236,13 @@
return 0
for(var/obj/obstacle in src)
- if(istype(obstacle, /obj/machinery/door) && !obstacle:air_properties_vary_with_direction)
+ if(istype(obstacle, /obj/machinery/door) && !(obstacle:air_properties_vary_with_direction))
continue
if(!obstacle.CanPass(null, T, 1.5, 1))
return 0
for(var/obj/obstacle in T)
- if(istype(obstacle, /obj/machinery/door) && !obstacle:air_properties_vary_with_direction)
+ if(istype(obstacle, /obj/machinery/door) && !(obstacle:air_properties_vary_with_direction))
continue
if(!obstacle.CanPass(null, src, 1.5, 1))
return 0
@@ -312,13 +258,13 @@
return 0
for(var/obj/obstacle in src)
- if(istype(obstacle, /obj/machinery/door) && !obstacle:air_properties_vary_with_direction)
+ if(istype(obstacle, /obj/machinery/door) && !(obstacle:air_properties_vary_with_direction))
continue
if(!obstacle.CanPass(null, T, 0, 0))
return 0
for(var/obj/obstacle in T)
- if(istype(obstacle, /obj/machinery/door) && !obstacle:air_properties_vary_with_direction)
+ if(istype(obstacle, /obj/machinery/door) && !(obstacle:air_properties_vary_with_direction))
continue
if(!obstacle.CanPass(null, src, 0, 0))
return 0
diff --git a/code/ZAS/ZAS_Zones.dm b/code/ZAS/ZAS_Zones.dm
index 860f57cd37..37aabee83b 100644
--- a/code/ZAS/ZAS_Zones.dm
+++ b/code/ZAS/ZAS_Zones.dm
@@ -7,11 +7,15 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs
var/rebuild = 0 //If 1, zone will be rebuilt on next process. Not sure if used.
var/datum/gas_mixture/air //The air contents of the zone.
var/list/contents //All the tiles that are contained in this zone.
- var/list/connections // /connection objects which refer to connections with other zones, e.g. through a door.
- var/list/connected_zones //Parallels connections, but lists zones to which this one is connected and the number
- //of points they're connected at.
- var/list/closed_connection_zones //Same as connected_zones, but for zones where the door or whatever is closed.
var/list/unsimulated_tiles // Any space tiles in this list will cause air to flow out.
+
+ var/list/connections //connection objects which refer to connections with other zones, e.g. through a door.
+ var/list/direct_connections //connections which directly connect two zones.
+
+ var/list/connected_zones //Parallels connections, but lists zones to which this one is connected and the number
+ //of points they're connected at.
+ var/list/closed_connection_zones //Same as connected_zones, but for zones where the door or whatever is closed.
+
var/last_update = 0
var/progress = "nothing"
@@ -49,23 +53,22 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs
zones.Add(src)
- //LEGACY, DO NOT USE. Use the SoftDelete proc.
+//DO NOT USE. Use the SoftDelete proc.
/zone/Del()
//Ensuring the zone list doesn't get clogged with null values.
for(var/turf/simulated/T in contents)
RemoveTurf(T)
- air_master.tiles_to_reconsider_zones += T
+ air_master.ReconsiderTileZone(T)
for(var/zone/Z in connected_zones)
if(src in Z.connected_zones)
Z.connected_zones.Remove(src)
- for(var/connection/C in connections)
- air_master.connections_to_check += C
+ air_master.AddConnectionToCheck(connections)
zones.Remove(src)
air = null
. = ..()
- //Handles deletion via garbage collection.
+//Handles deletion via garbage collection.
/zone/proc/SoftDelete()
zones.Remove(src)
air = null
@@ -73,7 +76,7 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs
//Ensuring the zone list doesn't get clogged with null values.
for(var/turf/simulated/T in contents)
RemoveTurf(T)
- air_master.tiles_to_reconsider_zones += T
+ air_master.ReconsiderTileZone(T)
//Removing zone connections and scheduling connection cleanup
for(var/zone/Z in connected_zones)
@@ -81,8 +84,7 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs
Z.connected_zones.Remove(src)
connected_zones = null
- for(var/connection/C in connections)
- air_master.connections_to_check += C
+ air_master.AddConnectionToCheck(connections)
connections = null
return 1
@@ -99,7 +101,9 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs
contents += T
if(air)
air.group_multiplier++
+
T.zone = src
+
else
if(!unsimulated_tiles)
unsimulated_tiles = list()
@@ -116,8 +120,13 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs
contents -= T
if(air)
air.group_multiplier--
+
if(T.zone == src)
T.zone = null
+
+ if(!contents.len)
+ SoftDelete()
+
else if(unsimulated_tiles)
unsimulated_tiles -= T
if(!unsimulated_tiles.len)
@@ -226,17 +235,13 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs
progress = "problem with: ZMerge(), a couple of misc procs"
- for(var/connection/C in connections)
- //Check if the connection is valid first.
- if(!C.Cleanup())
- continue
+ if(length(direct_connections))
+ for(var/connection/C in direct_connections)
- //Do merging if conditions are met. Specifically, if there's a non-door connection
- //to somewhere with space, the zones are merged regardless of equilibrium, to speed
- //up spacing in areas with double-plated windows.
- if(C && C.A.zone && C.B.zone)
- //indirect = 2 is a direct connection.
- if( C.indirect == 2 )
+ //Do merging if conditions are met. Specifically, if there's a non-door connection
+ //to somewhere with space, the zones are merged regardless of equilibrium, to speed
+ //up spacing in areas with double-plated windows.
+ if(C.A.zone && C.B.zone)
if(C.A.zone.air.compare(C.B.zone.air) || unsimulated_tiles)
ZMerge(C.A.zone,C.B.zone)
@@ -266,6 +271,7 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs
//If that zone has already processed, skip it.
if(Z.last_update > last_update)
continue
+
if(air && Z.air)
if( abs(air.temperature - Z.air.temperature) > vsc.connection_temperature_delta )
ShareHeat(air, Z.air, closed_connection_zones[Z])
@@ -383,7 +389,7 @@ proc/ShareSpace(datum/gas_mixture/A, list/unsimulated_tiles, dbg_output)
unsim_co2 *= correction_ratio
unsim_nitrogen *= correction_ratio
unsim_plasma *= correction_ratio
- unsim_heat_capacity = HEAT_CAPACITY_CALCULATION(unsim_oxygen,unsim_co2,unsim_nitrogen,unsim_plasma)
+ unsim_heat_capacity = HEAT_CAPACITY_CALCULATION(unsim_oxygen, unsim_co2, unsim_nitrogen, unsim_plasma)
var
ratio = sharing_lookup_table[6]
@@ -402,6 +408,9 @@ proc/ShareSpace(datum/gas_mixture/A, list/unsimulated_tiles, dbg_output)
co2_avg = (full_co2 + unsim_co2) / (size + share_size)
plasma_avg = (full_plasma + unsim_plasma) / (size + share_size)
+ temp_avg = 0
+
+ if((full_heat_capacity + unsim_heat_capacity) > 0)
temp_avg = (A.temperature * full_heat_capacity + unsim_temperature * unsim_heat_capacity) / (full_heat_capacity + unsim_heat_capacity)
if(sharing_lookup_table.len >= unsimulated_tiles.len) //6 or more interconnecting tiles will max at 42% of air moved per tick.
@@ -451,72 +460,146 @@ proc/ShareHeat(datum/gas_mixture/A, datum/gas_mixture/B, connecting_tiles)
///////////////////
//Zone Rebuilding//
///////////////////
+//Used for updating zone geometry when a zone is cut into two parts.
zone/proc/Rebuild()
+ var/list/new_zone_contents = IsolateContents()
+ if(new_zone_contents.len == 1)
+ return
+
+ var/list/current_contents
+ var/list/new_zones = list()
+
+ contents = new_zone_contents[1]
+ air.group_multiplier = contents.len
+
+ for(var/identifier in 2 to new_zone_contents.len)
+ current_contents = new_zone_contents[identifier]
+ var/zone/new_zone = new (current_contents)
+ new_zone.air.copy_from(air)
+ new_zones += new_zone
+
+ for(var/connection/connection in connections)
+ connection.Cleanup()
+
+ var/turf/simulated/adjacent
+
+ for(var/turf/unsimulated in unsimulated_tiles)
+ for(var/direction in cardinal)
+ adjacent = get_step(unsimulated, direction)
+
+ if(istype(adjacent) && adjacent.CanPass(null, unsimulated, 0, 0))
+ for(var/zone/zone in new_zones)
+ if(adjacent in zone)
+ zone.AddTurf(unsimulated)
+
+
+//Implements a two-pass connected component labeling algorithm to determine if the zone is, in fact, split.
+
+/zone/proc/IsolateContents()
+ var/list/current_adjacents = list()
+ var/adjacent_id
+ var/lowest_id
+
+ var/list/identical_ids = list()
+ var/list/turfs = contents.Copy()
+ var/current_identifier = 1
+
+ for(var/turf/simulated/current in turfs)
+ lowest_id = null
+ current_adjacents = list()
+
+ for(var/direction in cardinal)
+ if( !(current.air_check_directions & direction))
+ continue
+ var/turf/simulated/adjacent = get_step(current, direction)
+ if(adjacent in turfs)
+ current_adjacents += adjacent
+ adjacent_id = turfs[adjacent]
+
+ if(adjacent_id && (!lowest_id || adjacent_id < lowest_id))
+ lowest_id = adjacent_id
+
+ if(!lowest_id)
+ lowest_id = current_identifier++
+ identical_ids += lowest_id
+
+ for(var/turf/simulated/adjacent in current_adjacents)
+ adjacent_id = turfs[adjacent]
+ if(adjacent_id != lowest_id)
+ if(adjacent_id)
+ identical_ids[adjacent_id] = lowest_id
+ turfs[adjacent] = lowest_id
+ turfs[current] = lowest_id
+
+ var/list/final_arrangement = list()
+
+ for(var/turf/simulated/current in turfs)
+ current_identifier = identical_ids[turfs[current]]
+
+ if( current_identifier > final_arrangement.len )
+ final_arrangement.len = current_identifier
+ final_arrangement[current_identifier] = list(current)
+
+ else
+ final_arrangement[current_identifier] += current
+
+ //lazy but fast
+ final_arrangement.Remove(null)
+
+ return final_arrangement
+
+
+/*
+ if(!RequiresRebuild())
+ return
+
//Choose a random turf and regenerate the zone from it.
- var
- turf/simulated/sample = locate() in contents
- list/new_contents
- problem = 0
+ var/list/new_contents
+ var/list/new_unsimulated
- //
- var/list/turfs_to_consider = contents.Copy()
+ var/list/turfs_needing_zones = list()
- while(!sample || !sample.CanPass(null, sample, 1.5, 1))
- if(sample)
- turfs_to_consider.Remove(sample)
- sample = locate() in turfs_to_consider
- if(!sample)
- break
+ var/list/zones_to_check_connections = list(src)
- if(!istype(sample) || !sample.CanPass(null, sample, 1.5, 1)) //Not a single valid turf.
- for(var/turf/simulated/T in contents)
- air_master.tiles_to_update |= T
+ if(!locate(/turf/simulated/floor) in contents)
+ for(var/turf/simulated/turf in contents)
+ air_master.ReconsiderTileZone(turf)
return SoftDelete()
- new_contents = FloodFill(sample)
+ var/turfs_to_ignore = list()
+ if(direct_connections)
+ for(var/connection/connection in direct_connections)
+ if(connection.A.zone != src)
+ turfs_to_ignore += A
+ else if(connection.B.zone != src)
+ turfs_to_ignore += B
- var/list/new_unsimulated = ( unsimulated_tiles ? unsimulated_tiles : list() )
+ new_unsimulated = ( unsimulated_tiles ? unsimulated_tiles : list() )
+ //Now, we have allocated the new turfs into proper lists, and we can start actually rebuilding.
+
+ //If something isn't carried over, it will need a new zone.
+ for(var/turf/T in contents)
+ if(!(T in new_contents))
+ RemoveTurf(T)
+ turfs_needing_zones += T
+
+ //Handle addition of new turfs
for(var/turf/S in new_contents)
if(!istype(S, /turf/simulated))
new_unsimulated |= S
new_contents.Remove(S)
- if(contents.len != new_contents.len)
- problem = 1
+ //If something new is added, we need to deal with it seperately.
+ else if(!(S in contents) && istype(S, /turf/simulated))
+ if(!(S.zone in zones_to_check_connections))
+ zones_to_check_connections += S.zone
- //If something isn't carried over, there was a complication.
- for(var/turf/T in contents)
- if(!(T in new_contents))
- T.zone = null
- problem = 1
+ S.zone.RemoveTurf(S)
+ AddTurf(S)
- if(problem)
- //Build some new zones for stuff that wasn't included.
- var/list/turf/simulated/rebuild_turfs = contents - new_contents
- var/list/turf/simulated/reconsider_turfs = list()
- contents = new_contents
- for(var/turf/simulated/T in rebuild_turfs)
- if(!T.zone && T.CanPass(null, T, 1.5, 1))
- var/zone/Z = new /zone(T)
- Z.air.copy_from(air)
- else
- reconsider_turfs |= T
- for(var/turf/simulated/T in reconsider_turfs)
- if(!T.zone && T.CanPass(null, T, 1.5, 1))
- var/zone/Z = new /zone(T)
- Z.air.copy_from(air)
- else if(!T in air_master.tiles_to_update)
- air_master.tiles_to_update.Add(T)
-
- for(var/turf/simulated/T in contents)
- if(T.zone && T.zone != src)
- T.zone.RemoveTurf(T)
- T.zone = src
- else if(!T.zone)
- T.zone = src
- air.group_multiplier = contents.len
+ //Handle the addition of new unsimulated tiles.
unsimulated_tiles = null
if(new_unsimulated.len)
@@ -528,20 +611,13 @@ zone/proc/Rebuild()
if(istype(T) && T.zone && S.CanPass(null, T, 0, 0))
T.zone.AddTurf(S)
-//UNUSED
-/*
-zone/proc/connected_zones()
- //A legacy proc for getting connected zones.
- . = list()
- for(var/connection/C in connections)
- var/zone/Z
- if(C.A.zone == src)
- Z = C.B.zone
- else
- Z = C.A.zone
+ //Finally, handle the orphaned turfs
+
+ for(var/turf/simulated/T in turfs_needing_zones)
+ if(!T.zone)
+ zones_to_check_connections += new /zone(T)
+
+ for(var/zone/zone in zones_to_check_connections)
+ for(var/connection/C in zone.connections)
+ C.Cleanup()*/
- if(Z in .)
- .[Z]++
- else
- . += Z
- .[Z] = 1*/
diff --git a/code/controllers/master_controller.dm b/code/controllers/master_controller.dm
index f880ad66d8..d3ddef9f37 100644
--- a/code/controllers/master_controller.dm
+++ b/code/controllers/master_controller.dm
@@ -57,7 +57,7 @@ datum/controller/game_controller/proc/setup()
if(!air_master)
air_master = new /datum/controller/air_system()
- air_master.setup()
+ air_master.Setup()
if(!ticker)
ticker = new /datum/controller/gameticker()
@@ -127,8 +127,7 @@ datum/controller/game_controller/proc/process()
timer = world.timeofday
last_thing_processed = air_master.type
- air_master.current_cycle++
- if(!air_master.tick()) //Runtimed.
+ if(!air_master.Tick()) //Runtimed.
air_master.failed_ticks++
if(air_master.failed_ticks > 5)
world << "RUNTIMES IN ATMOS TICKER. Killing air simulation!"
@@ -137,7 +136,8 @@ datum/controller/game_controller/proc/process()
log_admin("ZASALERT: unable run zone/process() -- [air_master.tick_progress]")
air_processing_killed = 1
air_master.failed_ticks = 0
- air_cost = (world.timeofday - timer) / 10
+
+ air_cost = (world.timeofday - timer) / 10
sleep(breather_ticks)
diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm
index 6aec44f7f1..0f64866f45 100644
--- a/code/game/machinery/doors/door.dm
+++ b/code/game/machinery/doors/door.dm
@@ -257,36 +257,12 @@
return 1
/obj/machinery/door/proc/update_nearby_tiles(need_rebuild)
- if(!air_master) return 0
+ if(!air_master)
+ return 0
- var/turf/simulated/source = loc
- var/turf/simulated/north = get_step(source,NORTH)
- var/turf/simulated/south = get_step(source,SOUTH)
- var/turf/simulated/east = get_step(source,EAST)
- var/turf/simulated/west = get_step(source,WEST)
-
- update_heat_protection(loc)
-
- if(istype(source)) air_master.tiles_to_update += source
- if(istype(north)) air_master.tiles_to_update += north
- if(istype(south)) air_master.tiles_to_update += south
- if(istype(east)) air_master.tiles_to_update += east
- if(istype(west)) air_master.tiles_to_update += west
-
- if(width > 1)
- var/turf/simulated/next_turf = src
- var/step_dir = turn(dir, 180)
- for(var/current_step = 2, current_step <= width, current_step++)
- next_turf = get_step(src, step_dir)
- north = get_step(next_turf, step_dir)
- east = get_step(next_turf, turn(step_dir, 90))
- south = get_step(next_turf, turn(step_dir, -90))
-
- update_heat_protection(next_turf)
-
- if(istype(north)) air_master.tiles_to_update |= north
- if(istype(south)) air_master.tiles_to_update |= south
- if(istype(east)) air_master.tiles_to_update |= east
+ for(var/turf/simulated/turf in locs)
+ update_heat_protection(turf)
+ air_master.AddTurfToUpdate(turf)
return 1
diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm
index 66184774c4..c8d0d4d110 100644
--- a/code/game/machinery/doors/windowdoor.dm
+++ b/code/game/machinery/doors/windowdoor.dm
@@ -15,13 +15,10 @@
/obj/machinery/door/window/update_nearby_tiles(need_rebuild)
- if(!air_master) return 0
+ if(!air_master)
+ return 0
- var/turf/simulated/source = get_turf(src)
- var/turf/simulated/target = get_step(source,dir)
-
- if(istype(source)) air_master.tiles_to_update |= source
- if(istype(target)) air_master.tiles_to_update |= target
+ air_master.AddTurfToUpdate(get_turf(src))
return 1
diff --git a/code/game/machinery/shieldgen.dm b/code/game/machinery/shieldgen.dm
index 6b657bda78..640fc00afc 100644
--- a/code/game/machinery/shieldgen.dm
+++ b/code/game/machinery/shieldgen.dm
@@ -27,19 +27,10 @@
//Looks like copy/pasted code... I doubt 'need_rebuild' is even used here - Nodrak
/obj/machinery/shield/proc/update_nearby_tiles(need_rebuild)
- if(!air_master) return 0
+ if(!air_master)
+ return 0
- var/turf/simulated/source = get_turf(src)
- var/turf/simulated/north = get_step(source,NORTH)
- var/turf/simulated/south = get_step(source,SOUTH)
- var/turf/simulated/east = get_step(source,EAST)
- var/turf/simulated/west = get_step(source,WEST)
-
- if(istype(source)) air_master.tiles_to_update |= source
- if(istype(north)) air_master.tiles_to_update |= north
- if(istype(south)) air_master.tiles_to_update |= south
- if(istype(east)) air_master.tiles_to_update |= east
- if(istype(west)) air_master.tiles_to_update |= west
+ air_master.AddTurfToUpdate(get_turf(src))
return 1
diff --git a/code/game/objects/effects/effect_system.dm b/code/game/objects/effects/effect_system.dm
index d3e7144297..c0f783c52d 100644
--- a/code/game/objects/effects/effect_system.dm
+++ b/code/game/objects/effects/effect_system.dm
@@ -1030,19 +1030,10 @@ steam.start() -- spawns the effect
proc/update_nearby_tiles(need_rebuild)
- if(!air_master) return 0
+ if(!air_master)
+ return 0
- var/turf/simulated/source = get_turf(src)
- var/turf/simulated/north = get_step(source,NORTH)
- var/turf/simulated/south = get_step(source,SOUTH)
- var/turf/simulated/east = get_step(source,EAST)
- var/turf/simulated/west = get_step(source,WEST)
-
- if(istype(source)) air_master.tiles_to_update |= source
- if(istype(north)) air_master.tiles_to_update |= north
- if(istype(south)) air_master.tiles_to_update |= south
- if(istype(east)) air_master.tiles_to_update |= east
- if(istype(west)) air_master.tiles_to_update |= west
+ air_master.AddTurfToUpdate(get_turf(src))
return 1
diff --git a/code/game/objects/structures/mineral_doors.dm b/code/game/objects/structures/mineral_doors.dm
index 04b3bdc19c..64e9623fca 100644
--- a/code/game/objects/structures/mineral_doors.dm
+++ b/code/game/objects/structures/mineral_doors.dm
@@ -156,20 +156,9 @@
return
proc/update_nearby_tiles(need_rebuild) //Copypasta from airlock code
- if(!air_master) return 0
-
- var/turf/simulated/source = loc
- var/turf/simulated/north = get_step(source,NORTH)
- var/turf/simulated/south = get_step(source,SOUTH)
- var/turf/simulated/east = get_step(source,EAST)
- var/turf/simulated/west = get_step(source,WEST)
-
- if(istype(source)) air_master.tiles_to_update += source
- if(istype(north)) air_master.tiles_to_update += north
- if(istype(south)) air_master.tiles_to_update += south
- if(istype(east)) air_master.tiles_to_update += east
- if(istype(west)) air_master.tiles_to_update += west
-
+ if(!air_master)
+ return 0
+ air_master.AddTurfToUpdate(get_turf(src))
return 1
/obj/structure/mineral_door/iron
diff --git a/code/game/objects/structures/windoor_assembly.dm b/code/game/objects/structures/windoor_assembly.dm
index 478f6989ba..f13f3f1dec 100644
--- a/code/game/objects/structures/windoor_assembly.dm
+++ b/code/game/objects/structures/windoor_assembly.dm
@@ -294,12 +294,9 @@ obj/structure/windoor_assembly/Del()
return
/obj/structure/windoor_assembly/proc/update_nearby_tiles(need_rebuild)
- if(!air_master) return 0
+ if(!air_master)
+ return 0
- var/turf/simulated/source = loc
- var/turf/simulated/target = get_step(source,dir)
-
- if(istype(source)) air_master.tiles_to_update += source
- if(istype(target)) air_master.tiles_to_update += target
+ air_master.AddTurfToUpdate(loc)
return 1
diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm
index bb38bbcd85..60799f618e 100644
--- a/code/game/objects/structures/window.dm
+++ b/code/game/objects/structures/window.dm
@@ -316,21 +316,9 @@
//This proc has to do with airgroups and atmos, it has nothing to do with smoothwindows, that's update_nearby_tiles().
/obj/structure/window/proc/update_nearby_tiles(need_rebuild)
- if(!air_master) return 0
- if(!dir in cardinal)
- var/turf/simulated/source = get_turf(src)
- if(istype(source))
- air_master.tiles_to_update |= source
- for(var/dir in cardinal)
- var/turf/simulated/target = get_step(source,dir)
- if(istype(target)) air_master.tiles_to_update |= target
- return 1
-
- var/turf/simulated/source = get_turf(src)
- var/turf/simulated/target = get_step(source,dir)
-
- if(istype(source)) air_master.tiles_to_update |= source
- if(istype(target)) air_master.tiles_to_update |= target
+ if(!air_master)
+ return 0
+ air_master.AddTurfToUpdate(get_turf(src))
return 1
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index dc15cc4c9d..1a5675609c 100644
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -231,8 +231,8 @@
W.zone = src.zone
W.zone.AddTurf(W)
- for(var/turf/simulated/T in orange(src,1))
- air_master.tiles_to_update.Add(T)
+ if(air_master)
+ air_master.AddTurfToUpdate(src)
W.levelupdate()
return W
@@ -252,8 +252,7 @@
W.zone.AddTurf(W)
if(air_master)
- for(var/turf/simulated/T in orange(src,1))
- air_master.tiles_to_update.Add(T)
+ air_master.AddTurfToUpdate(src)
W.levelupdate()
return W
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index 9cf56cb6ff..c7168d93af 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -581,11 +581,11 @@ var/list/admin_verbs_mod = list(
set category = "Debug"
set name = "Kill Air"
set desc = "Toggle Air Processing"
- if(kill_air)
- kill_air = 0
+ if(air_processing_killed)
+ air_processing_killed = 0
usr << "Enabled air processing."
else
- kill_air = 1
+ air_processing_killed = 1
usr << "Disabled air processing."
feedback_add_details("admin_verb","KA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
log_admin("[key_name(usr)] used 'kill air'.")
diff --git a/code/modules/admin/verbs/mapping.dm b/code/modules/admin/verbs/mapping.dm
index af7f4f545e..76f1b42046 100644
--- a/code/modules/admin/verbs/mapping.dm
+++ b/code/modules/admin/verbs/mapping.dm
@@ -161,6 +161,8 @@ var/intercom_range_display_status = 0
src.verbs += /client/proc/disable_movement
src.verbs += /client/proc/Zone_Info
src.verbs += /client/proc/Test_ZAS_Connection
+ src.verbs += /client/proc/ZoneTick
+ src.verbs += /client/proc/TestZASRebuild
//src.verbs += /client/proc/cmd_admin_rejuvenate
feedback_add_details("admin_verb","mDV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!