/turf //used for temperature calculations var/thermal_conductivity = 0.005 var/heat_capacity = 1 var/temperature_archived //list of open turfs adjacent to us var/list/atmos_adjacent_turfs //bitfield of dirs in which we are superconducitng var/atmos_supeconductivity = NONE var/is_openturf = FALSE // used by extools shizz. //used to determine whether we should archive var/archived_cycle = 0 var/current_cycle = 0 //used for mapping and for breathing while in walls (because that's a thing that needs to be accounted for...) //string parsed by /datum/gas/proc/copy_from_turf var/initial_gas_mix = OPENTURF_DEFAULT_ATMOS //approximation of MOLES_O2STANDARD and MOLES_N2STANDARD pending byond allowing constant expressions to be embedded in constant strings // If someone will place 0 of some gas there, SHIT WILL BREAK. Do not do that. /turf/open //used for spacewind var/pressure_difference = 0 var/pressure_direction = 0 var/turf/pressure_specific_target var/datum/gas_mixture/turf/air var/obj/effect/hotspot/active_hotspot var/planetary_atmos = FALSE //air will revert to initial_gas_mix over time var/list/atmos_overlay_types //gas IDs of current active gas overlays is_openturf = TRUE /turf/open/Initialize() if(!blocks_air) air = new air.copy_from_turf(src) update_air_ref() . = ..() /turf/open/Destroy() if(active_hotspot) QDEL_NULL(active_hotspot) // Adds the adjacent turfs to the current atmos processing for(var/T in atmos_adjacent_turfs) SSair.add_to_active(T) return ..() /// Function for Extools Atmos /turf/proc/update_air_ref() /////////////////GAS MIXTURE PROCS/////////////////// /turf/open/assume_air(datum/gas_mixture/giver) //use this for machines to adjust air if(!giver) return FALSE air.merge(giver) update_visuals() return TRUE /turf/open/remove_air(amount) var/datum/gas_mixture/ours = return_air() var/datum/gas_mixture/removed = ours.remove(amount) update_visuals() return removed /turf/open/proc/copy_air_with_tile(turf/open/T) if(istype(T)) air.copy_from(T.air) /turf/open/proc/copy_air(datum/gas_mixture/copy) if(copy) air.copy_from(copy) /turf/return_air() RETURN_TYPE(/datum/gas_mixture) var/datum/gas_mixture/GM = new GM.copy_from_turf(src) return GM /turf/open/return_air() RETURN_TYPE(/datum/gas_mixture) return air /turf/temperature_expose() if(temperature > heat_capacity) to_be_destroyed = TRUE /turf/proc/archive() temperature_archived = temperature /turf/open/archive() air.archive() archived_cycle = SSair.times_fired temperature_archived = temperature /turf/open/proc/eg_reset_cooldowns() /turf/open/proc/eg_garbage_collect() /turf/open/proc/get_excited() /turf/open/proc/set_excited() /////////////////////////GAS OVERLAYS////////////////////////////// /turf/open/proc/update_visuals() var/list/atmos_overlay_types = src.atmos_overlay_types // Cache for free performance var/list/new_overlay_types = list() var/static/list/nonoverlaying_gases = typecache_of_gases_with_no_overlays() if(!air) // 2019-05-14: was not able to get this path to fire in testing. Consider removing/looking at callers -Naksu if (atmos_overlay_types) for(var/overlay in atmos_overlay_types) vis_contents -= overlay src.atmos_overlay_types = null return for(var/id in air.get_gases()) if (nonoverlaying_gases[id]) continue var/gas_overlay = GLOB.meta_gas_overlays[id] if(gas_overlay && air.get_moles(id) > GLOB.meta_gas_visibility[META_GAS_MOLES_VISIBLE]) new_overlay_types += gas_overlay[min(FACTOR_GAS_VISIBLE_MAX, CEILING(air.get_moles(id) / MOLES_GAS_VISIBLE_STEP, 1))] if (atmos_overlay_types) for(var/overlay in atmos_overlay_types-new_overlay_types) //doesn't remove overlays that would only be added vis_contents -= overlay if (length(new_overlay_types)) if (atmos_overlay_types) vis_contents += new_overlay_types - atmos_overlay_types //don't add overlays that already exist else vis_contents += new_overlay_types UNSETEMPTY(new_overlay_types) src.atmos_overlay_types = new_overlay_types /turf/open/proc/set_visuals(list/new_overlay_types) if (atmos_overlay_types) for(var/overlay in atmos_overlay_types-new_overlay_types) //doesn't remove overlays that would only be added vis_contents -= overlay if (length(new_overlay_types)) if (atmos_overlay_types) vis_contents += new_overlay_types - atmos_overlay_types //don't add overlays that already exist else vis_contents += new_overlay_types UNSETEMPTY(new_overlay_types) src.atmos_overlay_types = new_overlay_types /proc/typecache_of_gases_with_no_overlays() . = list() for (var/gastype in subtypesof(/datum/gas)) var/datum/gas/gasvar = gastype if (!initial(gasvar.gas_overlay)) .[gastype] = TRUE /////////////////////////////SIMULATION/////////////////////////////////// /*#define LAST_SHARE_CHECK \ var/last_share = our_air.get_last_share();\ if(last_share > MINIMUM_AIR_TO_SUSPEND){\ our_excited_group.reset_cooldowns();\ cached_atmos_cooldown = 0;\ } else if(last_share > MINIMUM_MOLES_DELTA_TO_MOVE) {\ our_excited_group.dismantle_cooldown = 0;\ cached_atmos_cooldown = 0;\ } */ /turf/proc/process_cell(fire_count) SSair.remove_from_active(src) /turf/open/proc/equalize_pressure_in_zone(cyclenum) /turf/open/proc/consider_firelocks(turf/T2) var/reconsider_adj = FALSE for(var/obj/machinery/door/firedoor/FD in T2) if((FD.flags_1 & ON_BORDER_1) && get_dir(T2, src) != FD.dir) continue FD.emergency_pressure_stop() reconsider_adj = TRUE for(var/obj/machinery/door/firedoor/FD in src) if((FD.flags_1 & ON_BORDER_1) && get_dir(src, T2) != FD.dir) continue FD.emergency_pressure_stop() reconsider_adj = TRUE if(reconsider_adj) T2.ImmediateCalculateAdjacentTurfs() // We want those firelocks closed yesterday. /turf/proc/handle_decompression_floor_rip() /turf/open/floor/handle_decompression_floor_rip(sum) if(sum > 20 && prob(clamp(sum / 10, 0, 30))) remove_tile() /turf/open/process_cell(fire_count) //////////////////////////SPACEWIND///////////////////////////// /turf/open/proc/consider_pressure_difference(turf/T, difference) if(difference > pressure_difference) pressure_direction = get_dir(src, T) pressure_difference = difference SSair.high_pressure_delta[src] = TRUE /turf/open/proc/high_pressure_movements() var/diff = pressure_difference if(locate(/obj/structure/rack) in src) diff *= 0.1 else if(locate(/obj/structure/table) in src) diff *= 0.2 for(var/obj/M in src) if(!M.anchored && !M.pulledby && M.last_high_pressure_movement_air_cycle < SSair.times_fired) M.experience_pressure_difference(diff, pressure_direction, 0, pressure_specific_target) for(var/mob/M in src) if(!M.anchored && !M.pulledby && M.last_high_pressure_movement_air_cycle < SSair.times_fired) M.experience_pressure_difference(diff, pressure_direction, 0, pressure_specific_target) /* if(pressure_difference > 100) new /obj/effect/temp_visual/dir_setting/space_wind(src, pressure_direction, clamp(round(sqrt(pressure_difference) * 2), 10, 255)) */ /atom/movable/var/pressure_resistance = 10 /atom/movable/var/last_high_pressure_movement_air_cycle = 0 /atom/movable/proc/experience_pressure_difference(pressure_difference, direction, pressure_resistance_prob_delta = 0, throw_target) var/const/PROBABILITY_OFFSET = 25 var/const/PROBABILITY_BASE_PRECENT = 75 var/max_force = sqrt(pressure_difference)*(MOVE_FORCE_DEFAULT / 5) set waitfor = 0 var/move_prob = 100 if (pressure_resistance > 0) move_prob = (pressure_difference/pressure_resistance*PROBABILITY_BASE_PRECENT)-PROBABILITY_OFFSET move_prob += pressure_resistance_prob_delta if (move_prob > PROBABILITY_OFFSET && prob(move_prob) && (move_resist != INFINITY) && (!anchored && (max_force >= (move_resist * MOVE_FORCE_PUSH_RATIO))) || (anchored && (max_force >= (move_resist * MOVE_FORCE_FORCEPUSH_RATIO)))) step(src, direction) ////////////////////////SUPERCONDUCTIVITY///////////////////////////// /turf/proc/conductivity_directions() if(archived_cycle < SSair.times_fired) archive() return NORTH|SOUTH|EAST|WEST /turf/open/conductivity_directions() if(blocks_air) return ..() for(var/direction in GLOB.cardinals) var/turf/T = get_step(src, direction) if(!(T in atmos_adjacent_turfs) && !(atmos_supeconductivity & direction)) . |= direction /turf/proc/neighbor_conduct_with_src(turf/open/other) if(!other.blocks_air) //Open but neighbor is solid other.temperature_share_open_to_solid(src) else //Both tiles are solid other.share_temperature_mutual_solid(src, thermal_conductivity) temperature_expose(null, temperature, null) /turf/open/neighbor_conduct_with_src(turf/other) if(blocks_air) ..() return if(!other.blocks_air) //Both tiles are open var/turf/open/T = other T.air.temperature_share(air, WINDOW_HEAT_TRANSFER_COEFFICIENT) else //Solid but neighbor is open temperature_share_open_to_solid(other) SSair.add_to_active(src, 0) /turf/proc/super_conduct() var/conductivity_directions = conductivity_directions() archive() if(conductivity_directions) //Conduct with tiles around me for(var/direction in GLOB.cardinals) if(conductivity_directions & direction) var/turf/neighbor = get_step(src,direction) if(!neighbor.thermal_conductivity) continue if(neighbor.archived_cycle < SSair.times_fired) neighbor.archive() neighbor.neighbor_conduct_with_src(src) neighbor.consider_superconductivity() radiate_to_spess() finish_superconduction() /turf/proc/finish_superconduction(temp = temperature) //Make sure still hot enough to continue conducting heat if(temp < MINIMUM_TEMPERATURE_FOR_SUPERCONDUCTION) SSair.active_super_conductivity -= src return FALSE /turf/open/finish_superconduction() //Conduct with air on my tile if I have it if(!blocks_air) temperature = air.temperature_share(null, thermal_conductivity, temperature, heat_capacity) ..((blocks_air ? temperature : air.return_temperature())) /turf/proc/consider_superconductivity() if(!thermal_conductivity) return FALSE SSair.active_super_conductivity[src] = TRUE return TRUE /turf/open/consider_superconductivity(starting) if(planetary_atmos) return FALSE if(air.return_temperature() < (starting?MINIMUM_TEMPERATURE_START_SUPERCONDUCTION:MINIMUM_TEMPERATURE_FOR_SUPERCONDUCTION)) return FALSE if(air.heat_capacity() < M_CELL_WITH_RATIO) // Was: MOLES_CELLSTANDARD*0.1*0.05 Since there are no variables here we can make this a constant. return FALSE return ..() /turf/closed/consider_superconductivity(starting) if(temperature < (starting?MINIMUM_TEMPERATURE_START_SUPERCONDUCTION:MINIMUM_TEMPERATURE_FOR_SUPERCONDUCTION)) return FALSE return ..() /turf/proc/radiate_to_spess() //Radiate excess tile heat to space if(temperature > T0C) //Considering 0 degC as te break even point for radiation in and out var/delta_temperature = (temperature_archived - TCMB) //hardcoded space temperature if((heat_capacity > 0) && (abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)) var/heat = thermal_conductivity*delta_temperature* \ (heat_capacity*HEAT_CAPACITY_VACUUM/(heat_capacity+HEAT_CAPACITY_VACUUM)) temperature -= heat/heat_capacity temperature = max(temperature,T0C) //otherwise we just sorta get stuck at super cold temps forever /turf/open/proc/temperature_share_open_to_solid(turf/sharer) sharer.temperature = air.temperature_share(null, sharer.thermal_conductivity, sharer.temperature, sharer.heat_capacity) /turf/proc/share_temperature_mutual_solid(turf/sharer, conduction_coefficient) //to be understood var/delta_temperature = (temperature_archived - sharer.temperature_archived) if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER && heat_capacity && sharer.heat_capacity) var/heat = conduction_coefficient*delta_temperature* \ (heat_capacity*sharer.heat_capacity/(heat_capacity+sharer.heat_capacity)) temperature -= heat/heat_capacity sharer.temperature += heat/sharer.heat_capacity temperature = max(temperature,T0C) sharer.temperature = max(sharer.temperature,T0C)