mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-11 18:53:06 +00:00
223 lines
5.6 KiB
Plaintext
223 lines
5.6 KiB
Plaintext
//Global Functions
|
|
//Contents: FloodFill, ZMerge, ZConnect
|
|
|
|
proc/FloodFill(turf/simulated/start)
|
|
if(!istype(start))
|
|
return list()
|
|
var
|
|
list
|
|
open = list(start)
|
|
closed = list()
|
|
|
|
while(open.len)
|
|
var/turf/simulated/T = pick(open)
|
|
|
|
if(!istype(T))
|
|
open -= T
|
|
continue
|
|
|
|
for(var/d in cardinal)
|
|
var/turf/simulated/O = get_step(T,d)
|
|
|
|
if(istype(O) && !(O in open) && !(O in closed) && O.ZCanPass(T))
|
|
|
|
if(T.HasDoor())
|
|
//If they both have doors, then they are nto able to connect period.
|
|
if(O.HasDoor())
|
|
continue
|
|
|
|
//connect first to north and west
|
|
if(d == NORTH || d == WEST)
|
|
open += O
|
|
|
|
else
|
|
var/turf/simulated/W = get_step(O, WEST)
|
|
var/turf/simulated/N = get_step(O, NORTH)
|
|
|
|
if( !O.ZCanPass(N) && !O.ZCanPass(W) )
|
|
//If it cannot connect either to the north or west, connect it!
|
|
open += O
|
|
|
|
else if(!O.HasDoor())
|
|
open += O
|
|
|
|
else
|
|
if(d == SOUTH || d == EAST)
|
|
//doors prefer connecting to zones to the north or west
|
|
closed += O
|
|
|
|
else
|
|
//see if we need to force an attempted connection
|
|
//(there are no potentially viable zones to the north/west of the door)
|
|
var/turf/simulated/W = get_step(O, WEST)
|
|
var/turf/simulated/N = get_step(O, NORTH)
|
|
|
|
if( !O.ZCanPass(N) && !O.ZCanPass(W) )
|
|
//If it cannot connect either to the north or west, connect it!
|
|
closed += O
|
|
|
|
open -= T
|
|
closed += T
|
|
|
|
return closed
|
|
|
|
|
|
proc/ZMerge(zone/A,zone/B)
|
|
|
|
if(!istype(A) || !istype(B))
|
|
return
|
|
|
|
//Merges two zones so that they are one.
|
|
var
|
|
a_size = A.air.group_multiplier
|
|
b_size = B.air.group_multiplier
|
|
c_size = a_size + b_size
|
|
new_contents = A.contents + B.contents
|
|
|
|
//Set air multipliers to one so air represents gas per tile.
|
|
A.air.group_multiplier = 1
|
|
B.air.group_multiplier = 1
|
|
|
|
//Remove some air proportional to the size of this zone.
|
|
A.air.remove_ratio(a_size/c_size)
|
|
B.air.remove_ratio(b_size/c_size)
|
|
|
|
//Merge the gases and set the multiplier to the sum of the old ones.
|
|
A.air.merge(B.air)
|
|
A.air.group_multiplier = c_size
|
|
|
|
//Check for connections to merge into the new zone.
|
|
for(var/connection/C in B.connections)
|
|
if((C.A in new_contents) && (C.B in new_contents))
|
|
del C
|
|
continue
|
|
if(!A.connections) A.connections = list()
|
|
A.connections += C
|
|
|
|
//Add space tiles.
|
|
A.unsimulated_tiles += B.unsimulated_tiles
|
|
|
|
//Add contents.
|
|
A.contents = new_contents
|
|
|
|
//Set all the zone vars.
|
|
for(var/turf/simulated/T in B.contents)
|
|
T.zone = A
|
|
|
|
for(var/connection/C in A.connections)
|
|
C.Cleanup()
|
|
|
|
B.SoftDelete()
|
|
|
|
|
|
proc/ZConnect(turf/simulated/A,turf/simulated/B)
|
|
//Connects two zones by forming a connection object representing turfs A and B.
|
|
|
|
|
|
//Make sure that if it's space, it gets added to unsimulated_tiles instead.
|
|
if(!istype(B))
|
|
if(A.zone)
|
|
A.zone.AddTurf(B)
|
|
return
|
|
if(!istype(A))
|
|
if(B.zone)
|
|
B.zone.AddTurf(A)
|
|
return
|
|
|
|
if(!istype(A) || !istype(B))
|
|
return
|
|
|
|
//Make some preliminary checks to see if the connection is valid.
|
|
if(!A.zone || !B.zone) return
|
|
if(A.zone == B.zone) return
|
|
|
|
if(A.CanPass(null,B,0,1))
|
|
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))
|
|
return
|
|
|
|
new /connection(A,B)
|
|
|
|
/*
|
|
proc/ZDisconnect(turf/A,turf/B)
|
|
//Removes a zone connection. Can split zones in the case of a permanent barrier.
|
|
|
|
//If one of them doesn't have a zone, it might be space, so check for that.
|
|
if(A.zone && B.zone)
|
|
//If the two zones are different, just remove a connection.
|
|
if(A.zone != B.zone)
|
|
for(var/connection/C in A.zone.connections)
|
|
if((C.A == A && C.B == B) || (C.A == B && C.B == A))
|
|
del C
|
|
if(C)
|
|
C.Cleanup()
|
|
//If they're the same, split the zone at this line.
|
|
else
|
|
//Preliminary checks to prevent stupidity.
|
|
if(A == B) return
|
|
if(A.CanPass(0,B,0,0)) return
|
|
if(A.HasDoor(B) || B.HasDoor(A)) return
|
|
|
|
//Do a test fill. If turf B is still in the floodfill, then the zone isn't really split.
|
|
var/zone/oldzone = A.zone
|
|
var/list/test = FloodFill(A)
|
|
if(B in test) return
|
|
|
|
else
|
|
var/zone/Z = new(test,oldzone.air) //Create a new zone based on the old air and the test fill.
|
|
|
|
//Add connections from the old zone.
|
|
for(var/connection/C in oldzone.connections)
|
|
if((C.A in Z.contents) || (C.B in Z.contents))
|
|
if(!Z.connections) Z.connections = list()
|
|
Z.connections += C
|
|
C.Cleanup()
|
|
|
|
//Check for space.
|
|
for(var/turf/T in test)
|
|
T.check_for_space()
|
|
|
|
//Make a new, identical air mixture for the other zone.
|
|
var/datum/gas_mixture/Y_Air = new
|
|
Y_Air.copy_from(oldzone.air)
|
|
|
|
var/zone/Y = new(B,Y_Air) //Make a new zone starting at B and using Y_Air.
|
|
|
|
//Add relevant connections from old zone.
|
|
for(var/connection/C in oldzone.connections)
|
|
if((C.A in Y.contents) || (C.B in Y.contents))
|
|
if(!Y.connections) Y.connections = list()
|
|
Y.connections += C
|
|
C.Cleanup()
|
|
|
|
//Add the remaining space tiles to this zone.
|
|
for(var/turf/space/T in oldzone.unsimulated_tiles)
|
|
if(!(T in Z.unsimulated_tiles))
|
|
Y.AddSpace(T)
|
|
|
|
oldzone.air = null
|
|
del oldzone
|
|
else
|
|
if(B.zone)
|
|
if(istype(A,/turf/space))
|
|
B.zone.RemoveSpace(A)
|
|
else
|
|
for(var/connection/C in B.zone.connections)
|
|
if((C.A == A && C.B == B) || (C.A == B && C.B == A))
|
|
del C
|
|
if(C)
|
|
C.Cleanup()
|
|
if(A.zone)
|
|
if(istype(B,/turf/space))
|
|
A.zone.RemoveSpace(B)
|
|
else
|
|
for(var/connection/C in A.zone.connections)
|
|
if((C.A == A && C.B == B) || (C.A == B && C.B == A))
|
|
del C
|
|
if(C)
|
|
C.Cleanup()*/ |