/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)) vis_contents |= graphic_add if(LAZYLEN(graphic_remove)) vis_contents -= graphic_remove /turf/proc/update_air_properties() var/block = c_airblock(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 block = unsim.c_airblock(src) if(block & AIR_BLOCKED) //unsim.dbg(air_blocked, turn(180,d)) continue var/r_block = c_airblock(unsim) if(r_block & AIR_BLOCKED) continue if(istype(unsim, /turf/simulated)) var/turf/simulated/sim = unsim if(HAS_VALID_ZONE(sim)) SSair.connect(sim, src) // CHOMPAdd #define GET_ZONE_NEIGHBOURS(T, ret) \ ret = 0; \ if (T.zone) { \ for (var/_gzn_dir in GLOB.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; \ } \ } \ } \ } // CHOMPEnd /* 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() // CHOMPEdit Start /* if(!zone) return 1 var/check_dirs = get_zone_neighbours(src) var/unconnected_dirs = check_dirs #ifdef MULTIZAS var/to_check = cornerdirsz #else var/to_check = cornerdirs #endif */ if(!zone) return TRUE var/check_dirs GET_ZONE_NEIGHBOURS(src, check_dirs) . = check_dirs if (!(. & (. - 1))) return TRUE for(var/dir in GLOB.csrfz_check) // CHOMPEdit //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/connected_dirs = get_zone_neighbours(get_step(src, dir)) if(connected_dirs && (dir & reverse_dir[connected_dirs]) == dir) unconnected_dirs &= ~dir //they are, so unflag the cardinals in question */ 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 & GLOB.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 return !unconnected_dirs //helper for can_safely_remove_from_zone() /turf/simulated/proc/get_zone_neighbours(turf/simulated/T) . = 0 if(istype(T) && T.zone) #ifdef MULTIZAS var/to_check = cardinalz #else var/to_check = cardinal #endif for(var/dir in to_check) var/turf/simulated/other = get_step(T, dir) if(istype(other) && other.zone == T.zone && !(other.c_airblock(T) & AIR_BLOCKED) && get_dist(src, other) <= 1) . |= dir */ . = !. // CHOMPEdit End /turf/simulated/update_air_properties() if(zone && zone.invalid) c_copy_air() zone = null //Easier than iterating through the list at the zone. var/s_block // CHOMPEdit ATMOS_CANPASS_TURF(s_block, src, src) if(s_block & AIR_BLOCKED) #ifdef ZASDBG if(verbose) to_world("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() // CHOMPAdd 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 = unsim.c_airblock(src) if(block & AIR_BLOCKED) #ifdef ZASDBG if(verbose) to_world("[d] is blocked.") //unsim.dbg(air_blocked, turn(180,d)) #endif continue var/r_block = c_airblock(unsim) if(r_block & AIR_BLOCKED) #ifdef ZASDBG if(verbose) to_world("[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. We need to rebuild. if((previously_open & d) && istype(unsim, /turf/simulated)) var/turf/simulated/sim = unsim if(zone && sim.zone == zone) zone.rebuild() return continue open_directions |= d if(istype(unsim, /turf/simulated)) var/turf/simulated/sim = unsim sim.open_directions |= GLOB.reverse_dir[d] // CHOMPEdit if(TURF_HAS_VALID_ZONE(sim)) // CHOMPEdit //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) to_world("[d] is zone blocked.") //dbg(zone_blocked, d) #endif //Postpone this tile rather than exit, since a connection can still be made. if(!postponed) postponed = list() postponed.Add(sim) else sim.zone.add(src) #ifdef ZASDBG dbg(assigned) if(verbose) to_world("Added to [zone]") #endif else if(sim.zone != zone) #ifdef ZASDBG if(verbose) to_world("Connecting to [sim.zone]") #endif SSair.connect(src, sim) #ifdef ZASDBG else if(verbose) to_world("[d] has same zone.") else if(verbose) to_world("[d] has invalid zone.") #endif else //Postponing connections to tiles until a zone is assured. if(!postponed) postponed = list() postponed.Add(unsim) if(!TURF_HAS_VALID_ZONE(src)) //Still no zone, make a new one. CHOMPEdit var/zone/newzone = new/zone() 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/turf/T in postponed) 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(GAS_O2, oxygen, GAS_CO2, carbon_dioxide, GAS_N2, nitrogen, GAS_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[GAS_O2] = (oxygen/sum)*amount GM.gas[GAS_CO2] = (carbon_dioxide/sum)*amount GM.gas[GAS_N2] = (nitrogen/sum)*amount GM.gas[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(GAS_O2, oxygen, GAS_CO2, carbon_dioxide, GAS_N2, nitrogen, GAS_PHORON, phoron) air.group_multiplier = 1 air.volume = CELL_VOLUME /turf/simulated/proc/c_copy_air() if(!air) air = new/datum/gas_mixture air.copy_from(zone.air) air.group_multiplier = 1