Files
Aurora.3/code/ZAS/Turf.dm
Lohikar 122096cf80 Minor Explosion Fixes (#4351)
changes:
- Sleeps in ex_act() should no longer stall explosions (this could sometimes be significant).
- ZAS should no longer runtime when CSRFZ checks a non-simulated turf.
- throw_at() sleeps should no longer delay droplimb() calls.
2018-03-05 13:22:17 -06:00

314 lines
7.7 KiB
Plaintext

/turf/simulated/var/zone/zone
/turf/simulated/var/open_directions
/turf/var/needs_air_update = 0
/turf/var/datum/gas_mixture/air
/turf/simulated/proc/update_graphic(list/graphic_add = null, list/graphic_remove = null)
if (LAZYLEN(graphic_add))
add_overlay(graphic_add.Copy(), TRUE) // We need to copy because SSoverlay will mutate this list & add appearance objects.
if(LAZYLEN(graphic_remove))
cut_overlay(graphic_remove.Copy(), TRUE)
/turf/proc/update_air_properties()
var/block
ATMOS_CANPASS_TURF(block, src, src)
if(block & AIR_BLOCKED)
//dbg(blocked)
return 1
#ifdef MULTIZAS
for(var/d = 1, d < 64, d *= 2)
#else
for(var/d = 1, d < 16, d *= 2)
#endif
var/turf/unsim = get_step(src, d)
if(!unsim)
continue
ATMOS_CANPASS_TURF(block, unsim, src)
if(block & AIR_BLOCKED)
//unsim.dbg(air_blocked, turn(180,d))
continue
var/r_block
ATMOS_CANPASS_TURF(r_block, src, unsim)
if(r_block & AIR_BLOCKED)
continue
if(istype(unsim, /turf/simulated))
var/turf/simulated/sim = unsim
if(TURF_HAS_VALID_ZONE(sim))
SSair.connect(sim, src)
// Helper for can_safely_remove_from_zone().
#define GET_ZONE_NEIGHBOURS(T, ret) \
ret = 0; \
if (T.zone) { \
for (var/_gzn_dir in gzn_check) { \
var/turf/simulated/other = get_step(T, _gzn_dir); \
if (istype(other) && other.zone == T.zone) { \
var/block; \
ATMOS_CANPASS_TURF(block, other, T); \
if (!(block & AIR_BLOCKED)) { \
ret |= _gzn_dir; \
} \
} \
} \
} \
/*
Simple heuristic for determining if removing the turf from it's zone will not partition the zone (A very bad thing).
Instead of analyzing the entire zone, we only check the nearest 3x3 turfs surrounding the src turf.
This implementation may produce false negatives but it (hopefully) will not produce any false postiives.
*/
/turf/simulated/proc/can_safely_remove_from_zone()
if(!zone)
return 1
var/check_dirs
GET_ZONE_NEIGHBOURS(src, check_dirs)
. = check_dirs
for(var/dir in csrfz_check)
//for each pair of "adjacent" cardinals (e.g. NORTH and WEST, but not NORTH and SOUTH)
if((dir & check_dirs) == dir)
//check that they are connected by the corner turf
var/turf/simulated/T = get_step(src, dir)
if (!istype(T))
. &= ~dir
continue
var/connected_dirs
GET_ZONE_NEIGHBOURS(T, connected_dirs)
if(connected_dirs && (dir & reverse_dir[connected_dirs]) == dir)
. &= ~dir //they are, so unflag the cardinals in question
//it is safe to remove src from the zone if all cardinals are connected by corner turfs
. = !.
#undef GET_ZONE_NEIGHBOURS
/turf/simulated/update_air_properties()
if(zone && zone.invalid) //this turf's zone is in the process of being rebuilt
c_copy_air() //not very efficient :(
zone = null //Easier than iterating through the list at the zone.
var/s_block
ATMOS_CANPASS_TURF(s_block, src, src)
if(s_block & AIR_BLOCKED)
#ifdef ZASDBG
if(verbose) log_debug("Self-blocked.")
//dbg(blocked)
#endif
if(zone)
var/zone/z = zone
if(can_safely_remove_from_zone()) //Helps normal airlocks avoid rebuilding zones all the time
c_copy_air() //we aren't rebuilding, but hold onto the old air so it can be readded
z.remove(src)
else
z.rebuild()
return 1
var/previously_open = open_directions
open_directions = 0
var/list/postponed
#ifdef MULTIZAS
for(var/d = 1, d < 64, d *= 2)
#else
for(var/d = 1, d < 16, d *= 2)
#endif
var/turf/unsim = get_step(src, d)
if(!unsim) //edge of map
continue
var/block
ATMOS_CANPASS_TURF(block, unsim, src)
if(block & AIR_BLOCKED)
#ifdef ZASDBG
if(verbose) log_debug("[d] is blocked.")
//unsim.dbg(air_blocked, turn(180,d))
#endif
continue
var/r_block
ATMOS_CANPASS_TURF(r_block, src, unsim)
if(r_block & AIR_BLOCKED)
#ifdef ZASDBG
if(verbose) log_debug("[d] is blocked.")
//dbg(air_blocked, d)
#endif
//Check that our zone hasn't been cut off recently.
//This happens when windows move or are constructed. Try to remove first, otherwise we need to rebuild.
if((previously_open & d) && istype(unsim, /turf/simulated))
var/turf/simulated/sim = unsim
if(zone && sim.zone == zone)
if (can_safely_remove_from_zone())
c_copy_air()
zone.remove(src)
else
zone.rebuild()
return
continue
open_directions |= d
if(istype(unsim, /turf/simulated))
var/turf/simulated/sim = unsim
sim.open_directions |= reverse_dir[d]
if(TURF_HAS_VALID_ZONE(sim))
//Might have assigned a zone, since this happens for each direction.
if(!zone)
//We do not merge if
// they are blocking us and we are not blocking them, or if
// we are blocking them and not blocking ourselves - this prevents tiny zones from forming on doorways.
if(((block & ZONE_BLOCKED) && !(r_block & ZONE_BLOCKED)) || ((r_block & ZONE_BLOCKED) && !(s_block & ZONE_BLOCKED)))
#ifdef ZASDBG
if(verbose) log_debug("[d] is zone blocked.")
//dbg(zone_blocked, d)
#endif
//Postpone this tile rather than exit, since a connection can still be made.
LAZYADD(postponed, sim)
else
sim.zone.add(src)
#ifdef ZASDBG
dbg(assigned)
if(verbose) log_debug("Added to [zone]")
#endif
else if(sim.zone != zone)
#ifdef ZASDBG
if(verbose) log_debug("Connecting to [sim.zone]")
#endif
SSair.connect(src, sim)
#ifdef ZASDBG
else if(verbose) log_debug("[d] has same zone.")
else if(verbose) log_debug("[d] has invalid zone.")
#endif
else
//Postponing connections to tiles until a zone is assured.
LAZYADD(postponed, unsim)
if(!TURF_HAS_VALID_ZONE(src)) //Still no zone, make a new one.
var/zone/newzone = new
newzone.add(src)
#ifdef ZASDBG
dbg(created)
ASSERT(zone)
#endif
//At this point, a zone should have happened. If it hasn't, don't add more checks, fix the bug.
for(var/thing in postponed)
var/turf/T = thing
SSair.connect(src, T)
/turf/proc/post_update_air_properties()
if(connections) connections.update_all()
/turf/assume_air(datum/gas_mixture/giver) //use this for machines to adjust air
return 0
/turf/proc/assume_gas(gasid, moles, temp = 0)
return 0
/turf/return_air()
//Create gas mixture to hold data for passing
var/datum/gas_mixture/GM = new
GM.adjust_multi("oxygen", oxygen, "carbon_dioxide", carbon_dioxide, "nitrogen", nitrogen, "phoron", phoron)
GM.temperature = temperature
return GM
/turf/remove_air(amount as num)
var/datum/gas_mixture/GM = new
var/sum = oxygen + carbon_dioxide + nitrogen + phoron
if(sum>0)
GM.gas["oxygen"] = (oxygen/sum)*amount
GM.gas["carbon_dioxide"] = (carbon_dioxide/sum)*amount
GM.gas["nitrogen"] = (nitrogen/sum)*amount
GM.gas["phoron"] = (phoron/sum)*amount
GM.temperature = temperature
GM.update_values()
return GM
/turf/simulated/assume_air(datum/gas_mixture/giver)
var/datum/gas_mixture/my_air = return_air()
my_air.merge(giver)
/turf/simulated/assume_gas(gasid, moles, temp = null)
var/datum/gas_mixture/my_air = return_air()
if(isnull(temp))
my_air.adjust_gas(gasid, moles)
else
my_air.adjust_gas_temp(gasid, moles, temp)
return 1
/turf/simulated/remove_air(amount as num)
var/datum/gas_mixture/my_air = return_air()
return my_air.remove(amount)
/turf/simulated/return_air()
if(zone)
if(!zone.invalid)
SSair.mark_zone_update(zone)
return zone.air
else
if(!air)
make_air()
c_copy_air()
return air
else
if(!air)
make_air()
return air
/turf/proc/make_air()
air = new/datum/gas_mixture
air.temperature = temperature
air.adjust_multi("oxygen", oxygen, "carbon_dioxide", carbon_dioxide, "nitrogen", nitrogen, "phoron", phoron)
air.group_multiplier = 1
air.volume = CELL_VOLUME
/turf/simulated/proc/c_copy_air()
if(!air)
air = new /datum/gas_mixture
air.group_multiplier = 1
air.copy_from(zone.air, TRUE)