mirror of
https://github.com/vgstation-coders/vgstation13.git
synced 2025-12-09 16:14:13 +00:00
Delayed Jungle setup until after air master initializes Master controller now properly ceases atmos simulation if runtimes occur (and are detected). Cleanup more ZAS stuff. FEA_system.dm, ZAS/ZAS_Turfs.dm, ZAS_Zones.dm. Canisters now autoconnect to portables connectors on creation. (Fixes airlocks not having attached canisters) Doors can now be made which respect directional door types (e.g. windoors and directional firelocks) and is handled better.
385 lines
10 KiB
Plaintext
385 lines
10 KiB
Plaintext
/*
|
|
This object is contained within zone/var/connections. It's generated whenever two turfs from different zones are linked.
|
|
Indirect connections will not merge the two zones after they reach equilibrium.
|
|
*/
|
|
#define CONNECTION_DIRECT 2
|
|
#define CONNECTION_INDIRECT 1
|
|
#define CONNECTION_CLOSED 0
|
|
|
|
|
|
connection
|
|
var
|
|
turf/simulated //The turfs involved in the connection.
|
|
A
|
|
B
|
|
zone
|
|
zone_A
|
|
zone_B
|
|
ref_A
|
|
ref_B
|
|
indirect = CONNECTION_DIRECT //If the connection is purely indirect, the zones should not join.
|
|
last_updated //The tick at which this was last updated.
|
|
no_zone_count = 0
|
|
|
|
|
|
New(turf/T,turf/O)
|
|
A = T
|
|
B = O
|
|
if(A.zone && B.zone)
|
|
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()
|
|
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]
|
|
connections.Add(src)
|
|
else
|
|
air_master.turfs_with_connections[ref_A] = list(src)
|
|
|
|
if(ref_B in air_master.turfs_with_connections)
|
|
var/list/connections = air_master.turfs_with_connections[ref_B]
|
|
connections.Add(src)
|
|
else
|
|
air_master.turfs_with_connections[ref_B] = list(src)
|
|
|
|
if(A.CanPass(null, B, 0, 0))
|
|
|
|
ConnectZones(A.zone, B.zone, 1)
|
|
|
|
if(A.HasDoor(B) || B.HasDoor(A))
|
|
indirect = CONNECTION_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)
|
|
|
|
|
|
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]
|
|
connections.Remove(src)
|
|
|
|
if(ref_A in air_master.turfs_with_connections)
|
|
var/list/connections = air_master.turfs_with_connections[ref_A]
|
|
connections.Remove(src)
|
|
|
|
//Ensure we delete the right values by sanity checkign right before deletion.
|
|
Sanitize()
|
|
|
|
//Remove connection from current zones.
|
|
if(A)
|
|
if(A.zone && A.zone.connections)
|
|
A.zone.connections.Remove(src)
|
|
if(!A.zone.connections.len)
|
|
A.zone.connections = null
|
|
if(B)
|
|
if(B.zone && B.zone.connections)
|
|
B.zone.connections.Remove(src)
|
|
if(!B.zone.connections.len)
|
|
B.zone.connections = null
|
|
|
|
//Disconnect zones while handling unusual conditions.
|
|
// e.g. loss of a zone on a turf
|
|
if(A && A.zone && B && B.zone)
|
|
DisconnectZones(A.zone, B.zone)
|
|
|
|
//Finally, preform actual deletion.
|
|
. = ..()
|
|
|
|
|
|
proc/ConnectZones(var/zone/zone_1, var/zone/zone_2, open = 0)
|
|
|
|
//Sanity checking
|
|
if(!istype(zone_1) || !istype(zone_2))
|
|
return
|
|
|
|
//Handle zones connecting indirectly/directly.
|
|
if(open)
|
|
|
|
//Create the lists if necessary.
|
|
if(!zone_1.connected_zones)
|
|
zone_1.connected_zones = list()
|
|
|
|
if(!zone_2.connected_zones)
|
|
zone_2.connected_zones = list()
|
|
|
|
//Increase the number of connections between zones.
|
|
if(zone_2 in zone_1.connected_zones)
|
|
zone_1.connected_zones[zone_2]++
|
|
else
|
|
zone_1.connected_zones += zone_2
|
|
zone_1.connected_zones[zone_2] = 1
|
|
|
|
if(zone_1 in zone_2.connected_zones)
|
|
zone_2.connected_zones[zone_1]++
|
|
else
|
|
zone_2.connected_zones += zone_1
|
|
zone_2.connected_zones[zone_1] = 1
|
|
|
|
//Handle closed connections.
|
|
else
|
|
|
|
//Create the lists
|
|
if(!zone_1.closed_connection_zones)
|
|
zone_1.closed_connection_zones = list()
|
|
|
|
if(!zone_2.closed_connection_zones)
|
|
zone_2.closed_connection_zones = list()
|
|
|
|
//Increment the connections.
|
|
if(zone_2 in zone_1.closed_connection_zones)
|
|
zone_1.closed_connection_zones[zone_2]++
|
|
else
|
|
zone_1.closed_connection_zones += zone_2
|
|
zone_1.closed_connection_zones[zone_2] = 1
|
|
|
|
if(zone_1 in zone_2.closed_connection_zones)
|
|
zone_2.closed_connection_zones[zone_1]++
|
|
else
|
|
zone_2.closed_connection_zones += zone_1
|
|
zone_2.closed_connection_zones[zone_1] = 1
|
|
|
|
|
|
proc/DisconnectZones(var/zone/zone_1, var/zone/zone_2)
|
|
|
|
//Sanity checking
|
|
if(!istype(zone_1) || !istype(zone_2))
|
|
return
|
|
|
|
//Handle disconnection of indirectly or directly connected zones.
|
|
if( (zone_1 in zone_2.connected_zones) || (zone_2 in zone_1.connected_zones) )
|
|
|
|
//If there are more than one connection, decrement the number of connections
|
|
//Otherwise, remove all connections between the zones.
|
|
if(zone_1.connected_zones[zone_2] > 1)
|
|
zone_1.connected_zones[zone_2]--
|
|
else
|
|
zone_1.connected_zones -= zone_2
|
|
//remove the list if it is empty
|
|
if(!zone_1.connected_zones.len)
|
|
zone_1.connected_zones = null
|
|
|
|
//Then do the same for the other zone.
|
|
if(zone_2.connected_zones[zone_1] > 1)
|
|
zone_2.connected_zones[zone_1]--
|
|
else
|
|
zone_2.connected_zones -= zone_1
|
|
if(!zone_2.connected_zones.len)
|
|
zone_2.connected_zones = null
|
|
|
|
//Handle disconnection of closed zones.
|
|
if( (zone_1 in zone_2.closed_connection_zones) || (zone_2 in zone_1.closed_connection_zones) )
|
|
|
|
//If there are more than one connection, decrement the number of connections
|
|
//Otherwise, remove all connections between the zones.
|
|
if(zone_1.closed_connection_zones[zone_2] > 1)
|
|
zone_1.closed_connection_zones[zone_2]--
|
|
else
|
|
zone_1.closed_connection_zones -= zone_2
|
|
//remove the list if it is empty
|
|
if(!zone_1.closed_connection_zones.len)
|
|
zone_1.closed_connection_zones = null
|
|
|
|
//Then do the same for the other zone.
|
|
if(zone_2.closed_connection_zones[zone_1] > 1)
|
|
zone_2.closed_connection_zones[zone_1]--
|
|
else
|
|
zone_2.closed_connection_zones -= zone_1
|
|
if(!zone_2.closed_connection_zones.len)
|
|
zone_2.closed_connection_zones = null
|
|
|
|
|
|
proc/Cleanup()
|
|
|
|
//Check sanity: existance of turfs
|
|
if(!A || !B)
|
|
del src
|
|
|
|
//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
|
|
|
|
//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
|
|
|
|
|
|
proc/CheckPassSanity()
|
|
//Sanity check, first.
|
|
Cleanup()
|
|
|
|
if(A.zone && B.zone)
|
|
|
|
//If no walls are blocking us...
|
|
if(A.ZAirPass(B))
|
|
//...we check to see if there is a door in the way...
|
|
var/door_pass = A.CanPass(null,B,1.5,1)
|
|
//...and if it is opened.
|
|
if(door_pass || A.CanPass(null,B,0,0))
|
|
|
|
//Make and remove connections to let air pass.
|
|
if(indirect == CONNECTION_CLOSED)
|
|
DisconnectZones(A.zone, B.zone)
|
|
ConnectZones(A.zone, B.zone, 1)
|
|
|
|
if(door_pass)
|
|
indirect = CONNECTION_DIRECT
|
|
else if(!door_pass)
|
|
indirect = CONNECTION_INDIRECT
|
|
|
|
//The door is instead closed.
|
|
else if(indirect > CONNECTION_CLOSED)
|
|
indirect = CONNECTION_CLOSED
|
|
|
|
DisconnectZones(A.zone, B.zone)
|
|
ConnectZones(A.zone, B.zone)
|
|
|
|
//If I can no longer pass air, better delete
|
|
else
|
|
del src
|
|
|
|
proc/Sanitize()
|
|
//If the zones change on connected turfs, update it.
|
|
|
|
//Both zones changed (wat)
|
|
if(A.zone && A.zone != zone_A && B.zone && B.zone != zone_B)
|
|
|
|
//If the zones have gotten swapped
|
|
// (do not ask me how, I am just being anal retentive about sanity)
|
|
if(A.zone == zone_B && B.zone == zone_A)
|
|
var/turf/temp = B
|
|
B = A
|
|
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.
|
|
if(zone_A && zone_A.connections)
|
|
zone_A.connections.Remove(src)
|
|
if(!zone_A.connections.len)
|
|
zone_A.connections = null
|
|
|
|
if(zone_B && zone_B.connections)
|
|
zone_B.connections.Remove(src)
|
|
if(!zone_B.connections.len)
|
|
zone_B.connections = null
|
|
|
|
if(A.zone)
|
|
if(!A.zone.connections)
|
|
A.zone.connections = list()
|
|
A.zone.connections |= src
|
|
|
|
if(B.zone)
|
|
if(!B.zone.connections)
|
|
B.zone.connections = list()
|
|
B.zone.connections |= src
|
|
|
|
//If either zone is null, we disconnect the archived ones after cleaning up the connections.
|
|
if(!A.zone || !B.zone)
|
|
if(zone_A && zone_B)
|
|
DisconnectZones(zone_B, zone_A)
|
|
|
|
if(!A.zone)
|
|
zone_A = A.zone
|
|
|
|
if(!B.zone)
|
|
zone_B = B.zone
|
|
return
|
|
|
|
//Handle diconnection and reconnection of zones.
|
|
if(zone_A && zone_B)
|
|
DisconnectZones(zone_A, zone_B)
|
|
ConnectZones(A.zone, B.zone, indirect)
|
|
|
|
//resetting values of archived values.
|
|
zone_B = B.zone
|
|
zone_A = A.zone
|
|
|
|
//The "A" zone changed.
|
|
else if(A.zone && A.zone != zone_A)
|
|
|
|
//Handle connection cleanup
|
|
if(zone_A)
|
|
if(zone_A.connections)
|
|
zone_A.connections.Remove(src)
|
|
if(!zone_A.connections.len)
|
|
zone_A.connections = null
|
|
|
|
if(A.zone)
|
|
if(!A.zone.connections)
|
|
A.zone.connections = list()
|
|
A.zone.connections |= src
|
|
|
|
//If the "A" zone is null, we disconnect the archived ones after cleaning up the connections.
|
|
if(!A.zone)
|
|
if(zone_A && zone_B)
|
|
DisconnectZones(zone_A, zone_B)
|
|
zone_A = A.zone
|
|
return
|
|
|
|
//Handle diconnection and reconnection of zones.
|
|
if(zone_A && zone_B)
|
|
DisconnectZones(zone_A, zone_B)
|
|
ConnectZones(A.zone, B.zone, indirect)
|
|
|
|
//The "B" zone changed.
|
|
else if(B.zone && B.zone != zone_B)
|
|
|
|
//Handle connection cleanup
|
|
if(zone_B)
|
|
if(zone_B.connections)
|
|
zone_B.connections.Remove(src)
|
|
if(!zone_B.connections.len)
|
|
zone_B.connections = null
|
|
|
|
if(B.zone)
|
|
if(!B.zone.connections)
|
|
B.zone.connections = list()
|
|
B.zone.connections |= src
|
|
|
|
//If the "B" zone is null, we disconnect the archived ones after cleaning up the connections.
|
|
if(!B.zone)
|
|
if(zone_A && zone_B)
|
|
DisconnectZones(zone_A, zone_B)
|
|
zone_B = B.zone
|
|
return
|
|
|
|
//Handle diconnection and reconnection of zones.
|
|
if(zone_A && zone_B)
|
|
DisconnectZones(zone_A, zone_B)
|
|
ConnectZones(A.zone, B.zone, indirect)
|
|
|
|
|
|
#undef CONNECTION_DIRECT
|
|
#undef CONNECTION_INDIRECT
|
|
#undef CONNECTION_CLOSED |