diff --git a/code/ZAS - vgstation/Airflow.dm b/code/ZAS - vg/Airflow.dm similarity index 70% rename from code/ZAS - vgstation/Airflow.dm rename to code/ZAS - vg/Airflow.dm index 04ee815bfc7..87f4bda7ecf 100644 --- a/code/ZAS - vgstation/Airflow.dm +++ b/code/ZAS - vg/Airflow.dm @@ -236,144 +236,144 @@ proc/AirflowSpace(zone/A) if(M) M.GotoAirflowDest(n/10) //Sometimes shit breaks, and M isn't there after the spawn. -atom/movable - var/tmp/turf/airflow_dest - var/tmp/airflow_speed = 0 - var/tmp/airflow_time = 0 - var/tmp/last_airflow = 0 - proc/GotoAirflowDest(n) - if(!zas_settings.Get(/datum/ZAS_Setting/airflow_push)) return // If not enabled, fuck it. - if(!airflow_dest) return - if(airflow_speed < 0) return - if(last_airflow > world.time - zas_settings.Get(/datum/ZAS_Setting/airflow_delay)) return - if(airflow_speed) - airflow_speed = n/max(get_dist(src,airflow_dest),1) +/atom/movable/var/tmp/turf/airflow_dest +/atom/movable/var/tmp/airflow_speed = 0 +/atom/movable/var/tmp/airflow_time = 0 +/atom/movable/var/tmp/last_airflow = 0 + +/atom/movable/proc/GotoAirflowDest(n) + if(!zas_settings.Get(/datum/ZAS_Setting/airflow_push)) return // If not enabled, fuck it. + if(!airflow_dest) return + if(airflow_speed < 0) return + if(last_airflow > world.time - zas_settings.Get(/datum/ZAS_Setting/airflow_delay)) return + if(airflow_speed) + airflow_speed = n/max(get_dist(src,airflow_dest),1) + return + last_airflow = world.time + if(airflow_dest == loc) + step_away(src,loc) + if(ismob(src)) + if(src:status_flags & GODMODE) return - last_airflow = world.time - if(airflow_dest == loc) - step_away(src,loc) - if(ismob(src)) - if(src:status_flags & GODMODE) + if(istype(src, /mob/living/carbon/human)) + if(src:buckled) return - if(istype(src, /mob/living/carbon/human)) - if(src:buckled) - return - if(src:shoes) - if(istype(src:shoes, /obj/item/clothing/shoes/magboots)) - if(src:shoes:magpulse) - return - src << "\red You are sucked away by airflow!" - var/airflow_falloff = 9 - ul_FalloffAmount(airflow_dest) //It's a fast falloff calc. Very useful. - if(airflow_falloff < 1) - airflow_dest = null - return - airflow_speed = min(max(n * (9/airflow_falloff),1),9) - var - xo = airflow_dest.x - src.x - yo = airflow_dest.y - src.y - od = 0 + if(src:shoes) + if(istype(src:shoes, /obj/item/clothing/shoes/magboots)) + if(src:shoes:magpulse) + return + src << "\red You are sucked away by airflow!" + var/airflow_falloff = 9 - ul_FalloffAmount(airflow_dest) //It's a fast falloff calc. Very useful. + if(airflow_falloff < 1) airflow_dest = null - if(!density) - density = 1 - od = 1 - while(airflow_speed > 0) - if(airflow_speed <= 0) return - airflow_speed = min(airflow_speed,15) - airflow_speed -= zas_settings.Get(/datum/ZAS_Setting/airflow_speed_decay) - if(airflow_speed > 7) - if(airflow_time++ >= airflow_speed - 7) - if(od) - density = 0 - sleep(1 * tick_multiplier) - else + return + airflow_speed = min(max(n * (9/airflow_falloff),1),9) + var + xo = airflow_dest.x - src.x + yo = airflow_dest.y - src.y + od = 0 + airflow_dest = null + if(!density) + density = 1 + od = 1 + while(airflow_speed > 0) + if(airflow_speed <= 0) return + airflow_speed = min(airflow_speed,15) + airflow_speed -= zas_settings.Get(/datum/ZAS_Setting/airflow_speed_decay) + if(airflow_speed > 7) + if(airflow_time++ >= airflow_speed - 7) if(od) density = 0 - sleep(max(1,10-(airflow_speed+3)) * tick_multiplier) - if(od) - density = 1 - if ((!( src.airflow_dest ) || src.loc == src.airflow_dest)) - src.airflow_dest = locate(min(max(src.x + xo, 1), world.maxx), min(max(src.y + yo, 1), world.maxy), src.z) - if ((src.x == 1 || src.x == world.maxx || src.y == 1 || src.y == world.maxy)) - return - if(!istype(loc, /turf)) - return - step_towards(src, src.airflow_dest) - if(ismob(src) && src:client) - src:client:move_delay = world.time + zas_settings.Get(/datum/ZAS_Setting/airflow_mob_slowdown) - airflow_dest = null - airflow_speed = 0 - airflow_time = 0 - if(od) - density = 0 - - - proc/RepelAirflowDest(n) - if(!zas_settings.Get(/datum/ZAS_Setting/airflow_push)) return // If not enabled, fuck it. - if(!airflow_dest) return - if(airflow_speed < 0) return - if(last_airflow > world.time - zas_settings.Get(/datum/ZAS_Setting/airflow_delay)) return - if(airflow_speed) - airflow_speed = n/max(get_dist(src,airflow_dest),1) - return - if(airflow_dest == loc) - step_away(src,loc) - if(ismob(src)) - if(src:status_flags & GODMODE) - return - if(istype(src, /mob/living/carbon/human)) - if(src:buckled) - return - if(src:shoes) - if(istype(src:shoes, /obj/item/clothing/shoes/magboots)) - if(src:shoes.flags & NOSLIP) - return - src << "\red You are pushed away by airflow!" - last_airflow = world.time - var/airflow_falloff = 9 - ul_FalloffAmount(airflow_dest) //It's a fast falloff calc. Very useful. - if(airflow_falloff < 1) - airflow_dest = null - return - airflow_speed = min(max(n * (9/airflow_falloff),1),9) - var - xo = -(airflow_dest.x - src.x) - yo = -(airflow_dest.y - src.y) - od = 0 - airflow_dest = null - if(!density) - density = 1 - od = 1 - while(airflow_speed > 0) - if(airflow_speed <= 0) return - airflow_speed = min(airflow_speed,15) - airflow_speed -= zas_settings.Get(/datum/ZAS_Setting/airflow_speed_decay) - if(airflow_speed > 7) - if(airflow_time++ >= airflow_speed - 7) - sleep(1 * tick_multiplier) - else - sleep(max(1,10-(airflow_speed+3)) * tick_multiplier) - if ((!( src.airflow_dest ) || src.loc == src.airflow_dest)) - src.airflow_dest = locate(min(max(src.x + xo, 1), world.maxx), min(max(src.y + yo, 1), world.maxy), src.z) - if ((src.x == 1 || src.x == world.maxx || src.y == 1 || src.y == world.maxy)) - return - if(!istype(loc, /turf)) - return - step_towards(src, src.airflow_dest) - if(ismob(src) && src:client) - src:client:move_delay = world.time + zas_settings.Get(/datum/ZAS_Setting/airflow_mob_slowdown) - airflow_dest = null - airflow_speed = 0 - airflow_time = 0 - if(od) - density = 0 - - Bump(atom/A) - if(airflow_speed > 0 && airflow_dest) - airflow_hit(A) + sleep(1 * tick_multiplier) else - airflow_speed = 0 - airflow_time = 0 - . = ..() + if(od) + density = 0 + sleep(max(1,10-(airflow_speed+3)) * tick_multiplier) + if(od) + density = 1 + if ((!( src.airflow_dest ) || src.loc == src.airflow_dest)) + src.airflow_dest = locate(min(max(src.x + xo, 1), world.maxx), min(max(src.y + yo, 1), world.maxy), src.z) + if ((src.x == 1 || src.x == world.maxx || src.y == 1 || src.y == world.maxy)) + return + if(!istype(loc, /turf)) + return + step_towards(src, src.airflow_dest) + if(ismob(src) && src:client) + src:client:move_delay = world.time + zas_settings.Get(/datum/ZAS_Setting/airflow_mob_slowdown) + airflow_dest = null + airflow_speed = 0 + airflow_time = 0 + if(od) + density = 0 + + +/atom/movable/proc/RepelAirflowDest(n) + if(!zas_settings.Get(/datum/ZAS_Setting/airflow_push)) return // If not enabled, fuck it. + if(!airflow_dest) return + if(airflow_speed < 0) return + if(last_airflow > world.time - zas_settings.Get(/datum/ZAS_Setting/airflow_delay)) return + if(airflow_speed) + airflow_speed = n/max(get_dist(src,airflow_dest),1) + return + if(airflow_dest == loc) + step_away(src,loc) + if(ismob(src)) + if(src:status_flags & GODMODE) + return + if(istype(src, /mob/living/carbon/human)) + if(src:buckled) + return + if(src:shoes) + if(istype(src:shoes, /obj/item/clothing/shoes/magboots)) + if(src:shoes.flags & NOSLIP) + return + src << "\red You are pushed away by airflow!" + last_airflow = world.time + var/airflow_falloff = 9 - ul_FalloffAmount(airflow_dest) //It's a fast falloff calc. Very useful. + if(airflow_falloff < 1) + airflow_dest = null + return + airflow_speed = min(max(n * (9/airflow_falloff),1),9) + var + xo = -(airflow_dest.x - src.x) + yo = -(airflow_dest.y - src.y) + od = 0 + airflow_dest = null + if(!density) + density = 1 + od = 1 + while(airflow_speed > 0) + if(airflow_speed <= 0) return + airflow_speed = min(airflow_speed,15) + airflow_speed -= zas_settings.Get(/datum/ZAS_Setting/airflow_speed_decay) + if(airflow_speed > 7) + if(airflow_time++ >= airflow_speed - 7) + sleep(1 * tick_multiplier) + else + sleep(max(1,10-(airflow_speed+3)) * tick_multiplier) + if ((!( src.airflow_dest ) || src.loc == src.airflow_dest)) + src.airflow_dest = locate(min(max(src.x + xo, 1), world.maxx), min(max(src.y + yo, 1), world.maxy), src.z) + if ((src.x == 1 || src.x == world.maxx || src.y == 1 || src.y == world.maxy)) + return + if(!istype(loc, /turf)) + return + step_towards(src, src.airflow_dest) + if(ismob(src) && src:client) + src:client:move_delay = world.time + zas_settings.Get(/datum/ZAS_Setting/airflow_mob_slowdown) + airflow_dest = null + airflow_speed = 0 + airflow_time = 0 + if(od) + density = 0 + +/atom/movable/Bump(atom/A) + if(airflow_speed > 0 && airflow_dest) + airflow_hit(A) + else + airflow_speed = 0 + airflow_time = 0 + . = ..() atom/movable/proc/airflow_hit(atom/A) airflow_speed = 0 @@ -429,6 +429,6 @@ zone/proc/movables() . = list() for(var/turf/T in contents) for(var/atom/A in T) - if(istype(A, /obj/effect) || istype(A, /mob/camera)) + if(istype(A, /obj/effect) || isobserver(A) || istype(A, /mob/camera)) continue . += A diff --git a/code/ZAS - vgstation/Connection.dm b/code/ZAS - vg/Connection.dm similarity index 100% rename from code/ZAS - vgstation/Connection.dm rename to code/ZAS - vg/Connection.dm diff --git a/code/ZAS - vgstation/Debug.dm b/code/ZAS - vg/Debug.dm similarity index 100% rename from code/ZAS - vgstation/Debug.dm rename to code/ZAS - vg/Debug.dm diff --git a/code/ZAS - vg/FEA_gas_mixture.dm b/code/ZAS - vg/FEA_gas_mixture.dm new file mode 100644 index 00000000000..37c53c8feda --- /dev/null +++ b/code/ZAS - vg/FEA_gas_mixture.dm @@ -0,0 +1,1055 @@ +/* +What are the archived variables for? + Calculations are done using the archived variables with the results merged into the regular variables. + This prevents race conditions that arise based on the order of tile processing. +*/ + +#define SPECIFIC_HEAT_TOXIN 200 +#define SPECIFIC_HEAT_AIR 20 +#define SPECIFIC_HEAT_CDO 30 +#define HEAT_CAPACITY_CALCULATION(oxygen,carbon_dioxide,nitrogen,toxins) \ + (carbon_dioxide*SPECIFIC_HEAT_CDO + (oxygen+nitrogen)*SPECIFIC_HEAT_AIR + toxins*SPECIFIC_HEAT_TOXIN) + +#define MINIMUM_HEAT_CAPACITY 0.0003 +#define QUANTIZE(variable) (round(variable,0.0001)) +#define TRANSFER_FRACTION 5 //What fraction (1/#) of the air difference to try and transfer + +#define TEMPERATURE_ICE_FORMATION 273.15 // 273 kelvin is the freezing point of water. +#define MIN_PRESSURE_ICE_FORMATION 10 // 10kPa should be okay + +#define GRAPHICS_PLASMA 1 +#define GRAPHICS_N2O 2 +#define GRAPHICS_REAGENTS 4 // Not used. Yet. +#define GRAPHICS_COLD 8 + + +/datum/gas/sleeping_agent/specific_heat = 40 //These are used for the "Trace Gases" stuff, but is buggy. + +/datum/gas/oxygen_agent_b/specific_heat = 300 + +/datum/gas/volatile_fuel/specific_heat = 30 + +/datum/gas + var/moles = 0 + + var/specific_heat = 0 + + var/moles_archived = 0 + +/datum/gas_mixture/ + var/oxygen = 0 //Holds the "moles" of each of the four gases. + var/carbon_dioxide = 0 + var/nitrogen = 0 + var/toxins = 0 + + var/total_moles = 0 //Updated when a reaction occurs. + + var/volume = CELL_VOLUME + + var/temperature = 0 //in Kelvin, use calculate_temperature() to modify + + var/group_multiplier = 1 + //Size of the group this gas_mixture is representing. + //=1 for singletons + + var/graphics=0 + + var/list/datum/gas/trace_gases = list() //Seemed to be a good idea that was abandoned + + var/tmp/oxygen_archived //These are variables for use with the archived data + var/tmp/carbon_dioxide_archived + var/tmp/nitrogen_archived + var/tmp/toxins_archived + + var/tmp/temperature_archived + + var/tmp/graphics_archived = 0 + var/tmp/fuel_burnt = 0 + +//FOR THE LOVE OF GOD PLEASE USE THIS PROC +//Call it with negative numbers to remove gases. + +/datum/gas_mixture/proc/adjust(o2 = 0, co2 = 0, n2 = 0, tx = 0, list/datum/gas/traces = list()) + //Purpose: Adjusting the gases within a airmix + //Called by: Nothing, yet! + //Inputs: The values of the gases to adjust + //Outputs: null + + oxygen = max(0, oxygen + o2) + carbon_dioxide = max(0, carbon_dioxide + co2) + nitrogen = max(0, nitrogen + n2) + toxins = max(0, toxins + tx) + + //handle trace gasses + for(var/datum/gas/G in traces) + var/datum/gas/T = locate(G.type) in trace_gases + if(T) + T.moles = max(G.moles + T.moles, 0) + else if(G.moles > 0) + trace_gases |= G + update_values() + return + +//tg seems to like using these a lot +/datum/gas_mixture/proc/return_temperature() + return temperature + + +/datum/gas_mixture/proc/return_volume() + return max(0, volume) + + +/datum/gas_mixture/proc/thermal_energy() + return temperature*heat_capacity() + +/////////////////////////////// +//PV=nRT - related procedures// +/////////////////////////////// + +/datum/gas_mixture/proc/heat_capacity() + //Purpose: Returning the heat capacity of the gas mix + //Called by: UNKNOWN + //Inputs: None + //Outputs: Heat capacity + + var/heat_capacity = HEAT_CAPACITY_CALCULATION(oxygen,carbon_dioxide,nitrogen,toxins) + + if(trace_gases && trace_gases.len) //sanity check because somehow the tracegases gets nulled? + for(var/datum/gas/trace_gas in trace_gases) + heat_capacity += trace_gas.moles*trace_gas.specific_heat + + return max(MINIMUM_HEAT_CAPACITY,heat_capacity) + +/datum/gas_mixture/proc/heat_capacity_archived() + //Purpose: Returning the archived heat capacity of the gas mix + //Called by: UNKNOWN + //Inputs: None + //Outputs: Archived heat capacity + + var/heat_capacity_archived = HEAT_CAPACITY_CALCULATION(oxygen_archived,carbon_dioxide_archived,nitrogen_archived,toxins_archived) + + if(trace_gases.len) + for(var/datum/gas/trace_gas in trace_gases) + heat_capacity_archived += trace_gas.moles_archived*trace_gas.specific_heat + + return max(MINIMUM_HEAT_CAPACITY,heat_capacity_archived) + +/datum/gas_mixture/proc/total_moles() + return total_moles + /*var/moles = oxygen + carbon_dioxide + nitrogen + toxins + + if(trace_gases.len) + for(var/datum/gas/trace_gas in trace_gases) + moles += trace_gas.moles + return moles*/ + +/datum/gas_mixture/proc/return_pressure() + //Purpose: Calculating Current Pressure + //Called by: + //Inputs: None + //Outputs: Gas pressure. + + if(volume>0) + return total_moles()*R_IDEAL_GAS_EQUATION*temperature/volume + return 0 + +// proc/return_temperature() + //Purpose: + //Inputs: + //Outputs: + +// return temperature + +// proc/return_volume() + //Purpose: + //Inputs: + //Outputs: + +// return max(0, volume) + +// proc/thermal_energy() + //Purpose: + //Inputs: + //Outputs: + +// return temperature*heat_capacity() + +/datum/gas_mixture/proc/update_values() + //Purpose: Calculating and storing values which were normally called CONSTANTLY + //Called by: Anything that changes values within a gas mix. + //Inputs: None + //Outputs: None + + total_moles = oxygen + carbon_dioxide + nitrogen + toxins + + if(trace_gases.len) + for(var/datum/gas/trace_gas in trace_gases) + total_moles += trace_gas.moles + + return + +//////////////////////////////////////////// +//Procedures used for very specific events// +//////////////////////////////////////////// + +/datum/gas_mixture/proc/check_tile_graphic() + //Purpose: Calculating the graphic for a tile + //Called by: Turfs updating + //Inputs: None + //Outputs: 1 if graphic changed, 0 if unchanged + + graphics = 0 + + // If configured and cold, maek ice + if(zas_settings.Get(/datum/ZAS_Setting/ice_formation)) + if(temperature <= TEMPERATURE_ICE_FORMATION && return_pressure()>MIN_PRESSURE_ICE_FORMATION) + // If we're just forming, do a probability check. Otherwise, KEEP IT ON~ + // This ordering will hopefully keep it from sampling random noise every damn tick. + //if(was_icy || (!was_icy && prob(25))) + graphics |= GRAPHICS_COLD + + if(toxins > MOLES_PLASMA_VISIBLE) + graphics |= GRAPHICS_PLASMA + if(length(trace_gases)) + var/datum/gas/sleeping_agent = locate(/datum/gas/sleeping_agent) in trace_gases + if(sleeping_agent && (sleeping_agent.moles > 1)) + graphics |= GRAPHICS_N2O + + /* + var/datum/gas/reagent = exact_locate(/datum/gas/reagent,trace_gases) + if(reagent && (reagent.moles > 0.1)) + graphics |= GRAPHICS_REAGENTS + */ + + return graphics != graphics_archived + +/datum/gas_mixture/proc/react(atom/dump_location) + //Purpose: Calculating if it is possible for a fire to occur in the airmix + //Called by: Air mixes updating? + //Inputs: None + //Outputs: If a fire occured + + var/reacting = 0 //set to 1 if a notable reaction occured (used by pipe_network) + + if(temperature > FIRE_MINIMUM_TEMPERATURE_TO_EXIST) + if(zburn(null) > 0) + reacting = 1 + + return reacting + +/datum/gas_mixture/proc/fire() + //Purpose: Calculating any fire reactions. + //Called by: react() (See above) + //Inputs: None + //Outputs: How much fuel burned + + return zburn(null) + + /*var/energy_released = 0 + var/old_heat_capacity = heat_capacity() + + var/datum/gas/volatile_fuel/fuel_store = locate(/datum/gas/volatile_fuel) in trace_gases + if(fuel_store) //General volatile gas burn + var/burned_fuel = 0 + + if(oxygen < fuel_store.moles) + burned_fuel = oxygen + fuel_store.moles -= burned_fuel + oxygen = 0 + else + burned_fuel = fuel_store.moles + oxygen -= fuel_store.moles + del(fuel_store) + + energy_released += FIRE_CARBON_ENERGY_RELEASED * burned_fuel + carbon_dioxide += burned_fuel + fuel_burnt += burned_fuel + + //Handle plasma burning + if(toxins > MINIMUM_HEAT_CAPACITY) + var/plasma_burn_rate = 0 + var/oxygen_burn_rate = 0 + //more plasma released at higher temperatures + var/temperature_scale + if(temperature > PLASMA_UPPER_TEMPERATURE) + temperature_scale = 1 + else + temperature_scale = (temperature-PLASMA_MINIMUM_BURN_TEMPERATURE)/(PLASMA_UPPER_TEMPERATURE-PLASMA_MINIMUM_BURN_TEMPERATURE) + if(temperature_scale > 0) + oxygen_burn_rate = 1.4 - temperature_scale + if(oxygen > toxins*PLASMA_OXYGEN_FULLBURN) + plasma_burn_rate = (toxins*temperature_scale)/4 + else + plasma_burn_rate = (temperature_scale*(oxygen/PLASMA_OXYGEN_FULLBURN))/4 + if(plasma_burn_rate > MINIMUM_HEAT_CAPACITY) + toxins -= plasma_burn_rate + oxygen -= plasma_burn_rate*oxygen_burn_rate + carbon_dioxide += plasma_burn_rate + + energy_released += FIRE_PLASMA_ENERGY_RELEASED * (plasma_burn_rate) + + fuel_burnt += (plasma_burn_rate)*(1+oxygen_burn_rate) + + if(energy_released > 0) + var/new_heat_capacity = heat_capacity() + if(new_heat_capacity > MINIMUM_HEAT_CAPACITY) + temperature = (temperature*old_heat_capacity + energy_released)/new_heat_capacity + update_values() + + return fuel_burnt*/ + +////////////////////////////////////////////// +//Procs for general gas spread calculations.// +////////////////////////////////////////////// + + +/datum/gas_mixture/proc/archive() + //Purpose: Archives the current gas values + //Called by: UNKNOWN + //Inputs: None + //Outputs: 1 + + oxygen_archived = oxygen + carbon_dioxide_archived = carbon_dioxide + nitrogen_archived = nitrogen + toxins_archived = toxins + + if(trace_gases.len) + for(var/datum/gas/trace_gas in trace_gases) + trace_gas.moles_archived = trace_gas.moles + + temperature_archived = temperature + + graphics_archived = graphics + + return 1 + +/datum/gas_mixture/proc/check_then_merge(datum/gas_mixture/giver) + //Purpose: Similar to merge(...) but first checks to see if the amount of air assumed is small enough + // that group processing is still accurate for source (aborts if not) + //Called by: airgroups/machinery expelling air, ? + //Inputs: The gas to try and merge + //Outputs: 1 on successful merge. 0 otherwise. + + if(!giver) + return 0 + if(((giver.oxygen > MINIMUM_AIR_TO_SUSPEND) && (giver.oxygen >= oxygen*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ + || ((giver.carbon_dioxide > MINIMUM_AIR_TO_SUSPEND) && (giver.carbon_dioxide >= carbon_dioxide*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ + || ((giver.nitrogen > MINIMUM_AIR_TO_SUSPEND) && (giver.nitrogen >= nitrogen*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ + || ((giver.toxins > MINIMUM_AIR_TO_SUSPEND) && (giver.toxins >= toxins*MINIMUM_AIR_RATIO_TO_SUSPEND))) + return 0 + if(abs(giver.temperature - temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) + return 0 + + if(giver.trace_gases.len) + for(var/datum/gas/trace_gas in giver.trace_gases) + var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases + if((trace_gas.moles > MINIMUM_AIR_TO_SUSPEND) && (!corresponding || (trace_gas.moles >= corresponding.moles*MINIMUM_AIR_RATIO_TO_SUSPEND))) + return 0 + + return merge(giver) + +/datum/gas_mixture/proc/merge(datum/gas_mixture/giver) + //Purpose: Merges all air from giver into self. Deletes giver. + //Called by: Machinery expelling air, check_then_merge, ? + //Inputs: The gas to merge. + //Outputs: 1 + + if(!giver) + return 0 + + if(abs(temperature-giver.temperature)>MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) + var/self_heat_capacity = heat_capacity()*group_multiplier + var/giver_heat_capacity = giver.heat_capacity()*giver.group_multiplier + var/combined_heat_capacity = giver_heat_capacity + self_heat_capacity + if(combined_heat_capacity != 0) + temperature = (giver.temperature*giver_heat_capacity + temperature*self_heat_capacity)/combined_heat_capacity + + if((group_multiplier>1)||(giver.group_multiplier>1)) + oxygen += giver.oxygen*giver.group_multiplier/group_multiplier + carbon_dioxide += giver.carbon_dioxide*giver.group_multiplier/group_multiplier + nitrogen += giver.nitrogen*giver.group_multiplier/group_multiplier + toxins += giver.toxins*giver.group_multiplier/group_multiplier + else + oxygen += giver.oxygen + carbon_dioxide += giver.carbon_dioxide + nitrogen += giver.nitrogen + toxins += giver.toxins + + if(giver.trace_gases.len) + for(var/datum/gas/trace_gas in giver.trace_gases) + var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases + if(!corresponding) + corresponding = new trace_gas.type() + trace_gases += corresponding + corresponding.moles += trace_gas.moles*giver.group_multiplier/group_multiplier + update_values() + + // Let the garbage collector handle it, faster according to /tg/ testers + //del(giver) + return 1 + +/datum/gas_mixture/proc/remove(amount) + //Purpose: Removes a certain number of moles from the air. + //Called by: ? + //Inputs: How many moles to remove. + //Outputs: Removed air. + + // Fix a singuloth problem + if(group_multiplier==0) + return null + + var/sum = total_moles() + amount = min(amount,sum) //Can not take more air than tile has! + if(amount <= 0) + return null + + var/datum/gas_mixture/removed = new + + + removed.oxygen = QUANTIZE((oxygen/sum)*amount) + removed.nitrogen = QUANTIZE((nitrogen/sum)*amount) + removed.carbon_dioxide = QUANTIZE((carbon_dioxide/sum)*amount) + removed.toxins = QUANTIZE((toxins/sum)*amount) + + oxygen -= removed.oxygen/group_multiplier + nitrogen -= removed.nitrogen/group_multiplier + carbon_dioxide -= removed.carbon_dioxide/group_multiplier + toxins -= removed.toxins/group_multiplier + + if(trace_gases.len) + for(var/datum/gas/trace_gas in trace_gases) + var/datum/gas/corresponding = new trace_gas.type() + removed.trace_gases += corresponding + + corresponding.moles = (trace_gas.moles/sum)*amount + trace_gas.moles -= corresponding.moles/group_multiplier + + removed.temperature = temperature + update_values() + removed.update_values() + + return removed + +/datum/gas_mixture/proc/remove_ratio(ratio) + //Purpose: Removes a certain ratio of the air. + //Called by: ? + //Inputs: Percentage to remove. + //Outputs: Removed air. + + if(ratio <= 0) + return null + + ratio = min(ratio, 1) + + var/datum/gas_mixture/removed = new + + removed.oxygen = QUANTIZE(oxygen*ratio) + removed.nitrogen = QUANTIZE(nitrogen*ratio) + removed.carbon_dioxide = QUANTIZE(carbon_dioxide*ratio) + removed.toxins = QUANTIZE(toxins*ratio) + + oxygen -= removed.oxygen/group_multiplier + nitrogen -= removed.nitrogen/group_multiplier + carbon_dioxide -= removed.carbon_dioxide/group_multiplier + toxins -= removed.toxins/group_multiplier + + if(trace_gases.len) + for(var/datum/gas/trace_gas in trace_gases) + var/datum/gas/corresponding = new trace_gas.type() + removed.trace_gases += corresponding + + corresponding.moles = trace_gas.moles*ratio + trace_gas.moles -= corresponding.moles/group_multiplier + + removed.temperature = temperature + update_values() + removed.update_values() + + return removed + +/datum/gas_mixture/proc/check_then_remove(amount) + //Purpose: Similar to remove(...) but first checks to see if the amount of air removed is small enough + // that group processing is still accurate for source (aborts if not) + //Called by: ? + //Inputs: Number of moles to remove + //Outputs: Removed air or 0 if it can remove air or not. + + amount = min(amount,total_moles()) //Can not take more air than tile has! + + if((amount > MINIMUM_AIR_RATIO_TO_SUSPEND) && (amount > total_moles()*MINIMUM_AIR_RATIO_TO_SUSPEND)) + return 0 + + return remove(amount) + +/datum/gas_mixture/proc/copy_from(datum/gas_mixture/sample) + //Purpose: Duplicates the sample air mixture. + //Called by: airgroups splitting, ? + //Inputs: Gas to copy + //Outputs: 1 + + oxygen = sample.oxygen + carbon_dioxide = sample.carbon_dioxide + nitrogen = sample.nitrogen + toxins = sample.toxins + total_moles = sample.total_moles() + + trace_gases.len=null + if(sample.trace_gases.len > 0) + for(var/datum/gas/trace_gas in sample.trace_gases) + var/datum/gas/corresponding = new trace_gas.type() + trace_gases += corresponding + + corresponding.moles = trace_gas.moles + + temperature = sample.temperature + + return 1 + +/datum/gas_mixture/proc/check_gas_mixture(datum/gas_mixture/sharer) + //Purpose: Telling if one or both airgroups needs to disable group processing. + //Called by: Airgroups sharing air, checking if group processing needs disabled. + //Inputs: Gas to compare from other airgroup + //Outputs: 0 if the self-check failed (local airgroup breaks?) + // then -1 if sharer-check failed (sharing airgroup breaks?) + // then 1 if both checks pass (share succesful?) + if(!istype(sharer)) + return + + var/delta_oxygen = QUANTIZE(oxygen_archived - sharer.oxygen_archived)/TRANSFER_FRACTION + var/delta_carbon_dioxide = QUANTIZE(carbon_dioxide_archived - sharer.carbon_dioxide_archived)/TRANSFER_FRACTION + var/delta_nitrogen = QUANTIZE(nitrogen_archived - sharer.nitrogen_archived)/TRANSFER_FRACTION + var/delta_toxins = QUANTIZE(toxins_archived - sharer.toxins_archived)/TRANSFER_FRACTION + + var/delta_temperature = (temperature_archived - sharer.temperature_archived) + + if(((abs(delta_oxygen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_oxygen) >= oxygen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ + || ((abs(delta_carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_carbon_dioxide) >= carbon_dioxide_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ + || ((abs(delta_nitrogen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_nitrogen) >= nitrogen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ + || ((abs(delta_toxins) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_toxins) >= toxins_archived*MINIMUM_AIR_RATIO_TO_SUSPEND))) + return 0 + + if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) + return 0 + + if(sharer.trace_gases.len) + for(var/datum/gas/trace_gas in sharer.trace_gases) + if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND*4) + var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases + if(corresponding) + if(trace_gas.moles_archived >= corresponding.moles_archived*MINIMUM_AIR_RATIO_TO_SUSPEND*4) + return 0 + else + return 0 + + if(trace_gases.len) + for(var/datum/gas/trace_gas in trace_gases) + if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND*4) + if(!locate(trace_gas.type) in sharer.trace_gases) + return 0 + + if(((abs(delta_oxygen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_oxygen) >= sharer.oxygen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ + || ((abs(delta_carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_carbon_dioxide) >= sharer.carbon_dioxide_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ + || ((abs(delta_nitrogen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_nitrogen) >= sharer.nitrogen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ + || ((abs(delta_toxins) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_toxins) >= sharer.toxins_archived*MINIMUM_AIR_RATIO_TO_SUSPEND))) + return -1 + + if(trace_gases.len) + for(var/datum/gas/trace_gas in trace_gases) + if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND*4) + var/datum/gas/corresponding = locate(trace_gas.type) in sharer.trace_gases + if(corresponding) + if(trace_gas.moles_archived >= corresponding.moles_archived*MINIMUM_AIR_RATIO_TO_SUSPEND*4) + return -1 + else + return -1 + + return 1 + +/datum/gas_mixture/proc/check_turf(turf/model) + //Purpose: Used to compare the gases in an unsimulated turf with the gas in a simulated one. + //Called by: Sharing air (mimicing) with adjacent unsimulated turfs + //Inputs: Unsimulated turf + //Outputs: 1 if safe to mimic, 0 if needs to break airgroup. + + var/delta_oxygen = (oxygen_archived - model.oxygen)/TRANSFER_FRACTION + var/delta_carbon_dioxide = (carbon_dioxide_archived - model.carbon_dioxide)/TRANSFER_FRACTION + var/delta_nitrogen = (nitrogen_archived - model.nitrogen)/TRANSFER_FRACTION + var/delta_toxins = (toxins_archived - model.toxins)/TRANSFER_FRACTION + + var/delta_temperature = (temperature_archived - model.temperature) + + if(((abs(delta_oxygen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_oxygen) >= oxygen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ + || ((abs(delta_carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_carbon_dioxide) >= carbon_dioxide_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ + || ((abs(delta_nitrogen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_nitrogen) >= nitrogen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ + || ((abs(delta_toxins) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_toxins) >= toxins_archived*MINIMUM_AIR_RATIO_TO_SUSPEND))) + return 0 + if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) + return 0 + + if(trace_gases.len) + for(var/datum/gas/trace_gas in trace_gases) + if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND*4) + return 0 + + return 1 + +/datum/gas_mixture/proc/share(datum/gas_mixture/sharer) + //Purpose: Used to transfer gas from a more pressurised tile to a less presurised tile + // (Two directional, if the other tile is more pressurised, air travels to current tile) + //Called by: Sharing air with adjacent simulated turfs + //Inputs: Air datum to share with + //Outputs: Amount of gas exchanged (Negative if lost air, positive if gained.) + + + if(!istype(sharer)) + return + + var/delta_oxygen = QUANTIZE(oxygen_archived - sharer.oxygen_archived)/TRANSFER_FRACTION + var/delta_carbon_dioxide = QUANTIZE(carbon_dioxide_archived - sharer.carbon_dioxide_archived)/TRANSFER_FRACTION + var/delta_nitrogen = QUANTIZE(nitrogen_archived - sharer.nitrogen_archived)/TRANSFER_FRACTION + var/delta_toxins = QUANTIZE(toxins_archived - sharer.toxins_archived)/TRANSFER_FRACTION + + var/delta_temperature = (temperature_archived - sharer.temperature_archived) + + var/old_self_heat_capacity = 0 + var/old_sharer_heat_capacity = 0 + + var/heat_self_to_sharer = 0 + var/heat_capacity_self_to_sharer = 0 + var/heat_sharer_to_self = 0 + var/heat_capacity_sharer_to_self = 0 + + if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) + + var/delta_air = delta_oxygen+delta_nitrogen + if(delta_air) + var/air_heat_capacity = SPECIFIC_HEAT_AIR*delta_air + if(delta_air > 0) + heat_self_to_sharer += air_heat_capacity*temperature_archived + heat_capacity_self_to_sharer += air_heat_capacity + else + heat_sharer_to_self -= air_heat_capacity*sharer.temperature_archived + heat_capacity_sharer_to_self -= air_heat_capacity + + if(delta_carbon_dioxide) + var/carbon_dioxide_heat_capacity = SPECIFIC_HEAT_CDO*delta_carbon_dioxide + if(delta_carbon_dioxide > 0) + heat_self_to_sharer += carbon_dioxide_heat_capacity*temperature_archived + heat_capacity_self_to_sharer += carbon_dioxide_heat_capacity + else + heat_sharer_to_self -= carbon_dioxide_heat_capacity*sharer.temperature_archived + heat_capacity_sharer_to_self -= carbon_dioxide_heat_capacity + + if(delta_toxins) + var/toxins_heat_capacity = SPECIFIC_HEAT_TOXIN*delta_toxins + if(delta_toxins > 0) + heat_self_to_sharer += toxins_heat_capacity*temperature_archived + heat_capacity_self_to_sharer += toxins_heat_capacity + else + heat_sharer_to_self -= toxins_heat_capacity*sharer.temperature_archived + heat_capacity_sharer_to_self -= toxins_heat_capacity + + old_self_heat_capacity = heat_capacity()*group_multiplier + old_sharer_heat_capacity = sharer.heat_capacity()*sharer.group_multiplier + + oxygen -= delta_oxygen/group_multiplier + sharer.oxygen += delta_oxygen/sharer.group_multiplier + + carbon_dioxide -= delta_carbon_dioxide/group_multiplier + sharer.carbon_dioxide += delta_carbon_dioxide/sharer.group_multiplier + + nitrogen -= delta_nitrogen/group_multiplier + sharer.nitrogen += delta_nitrogen/sharer.group_multiplier + + toxins -= delta_toxins/group_multiplier + sharer.toxins += delta_toxins/sharer.group_multiplier + + var/moved_moles = (delta_oxygen + delta_carbon_dioxide + delta_nitrogen + delta_toxins) + + var/list/trace_types_considered = list() + + if(trace_gases.len) + for(var/datum/gas/trace_gas in trace_gases) + + var/datum/gas/corresponding = locate(trace_gas.type) in sharer.trace_gases + var/delta = 0 + + if(corresponding) + delta = QUANTIZE(trace_gas.moles_archived - corresponding.moles_archived)/TRANSFER_FRACTION + else + corresponding = new trace_gas.type() + sharer.trace_gases += corresponding + + delta = trace_gas.moles_archived/TRANSFER_FRACTION + + trace_gas.moles -= delta/group_multiplier + corresponding.moles += delta/sharer.group_multiplier + + if(delta) + var/individual_heat_capacity = trace_gas.specific_heat*delta + if(delta > 0) + heat_self_to_sharer += individual_heat_capacity*temperature_archived + heat_capacity_self_to_sharer += individual_heat_capacity + else + heat_sharer_to_self -= individual_heat_capacity*sharer.temperature_archived + heat_capacity_sharer_to_self -= individual_heat_capacity + + moved_moles += delta + + trace_types_considered += trace_gas.type + + + if(sharer.trace_gases.len) + for(var/datum/gas/trace_gas in sharer.trace_gases) + if(trace_gas.type in trace_types_considered) continue + else + var/datum/gas/corresponding + var/delta = 0 + + corresponding = new trace_gas.type() + trace_gases += corresponding + + delta = trace_gas.moles_archived/TRANSFER_FRACTION + + trace_gas.moles -= delta/sharer.group_multiplier + corresponding.moles += delta/group_multiplier + + //Guaranteed transfer from sharer to self + var/individual_heat_capacity = trace_gas.specific_heat*delta + heat_sharer_to_self += individual_heat_capacity*sharer.temperature_archived + heat_capacity_sharer_to_self += individual_heat_capacity + + moved_moles += -delta + update_values() + sharer.update_values() + + if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) + var/new_self_heat_capacity = old_self_heat_capacity + heat_capacity_sharer_to_self - heat_capacity_self_to_sharer + var/new_sharer_heat_capacity = old_sharer_heat_capacity + heat_capacity_self_to_sharer - heat_capacity_sharer_to_self + + if(new_self_heat_capacity > MINIMUM_HEAT_CAPACITY) + temperature = (old_self_heat_capacity*temperature - heat_capacity_self_to_sharer*temperature_archived + heat_capacity_sharer_to_self*sharer.temperature_archived)/new_self_heat_capacity + + if(new_sharer_heat_capacity > MINIMUM_HEAT_CAPACITY) + sharer.temperature = (old_sharer_heat_capacity*sharer.temperature-heat_capacity_sharer_to_self*sharer.temperature_archived + heat_capacity_self_to_sharer*temperature_archived)/new_sharer_heat_capacity + + if(abs(old_sharer_heat_capacity) > MINIMUM_HEAT_CAPACITY) + if(abs(new_sharer_heat_capacity/old_sharer_heat_capacity - 1) < 0.10) // <10% change in sharer heat capacity + temperature_share(sharer, OPEN_HEAT_TRANSFER_COEFFICIENT) + + if((delta_temperature > MINIMUM_TEMPERATURE_TO_MOVE) || abs(moved_moles) > MINIMUM_MOLES_DELTA_TO_MOVE) + var/delta_pressure = temperature_archived*(total_moles() + moved_moles) - sharer.temperature_archived*(sharer.total_moles() - moved_moles) + return delta_pressure*R_IDEAL_GAS_EQUATION/volume + + else + return 0 + +/datum/gas_mixture/proc/mimic(turf/model, border_multiplier) + //Purpose: Used transfer gas from a more pressurised tile to a less presurised unsimulated tile. + //Called by: "sharing" from unsimulated to simulated turfs. + //Inputs: Unsimulated turf, Multiplier for gas transfer (optional) + //Outputs: Amount of gas exchanged + + var/delta_oxygen = QUANTIZE(oxygen_archived - model.oxygen)/TRANSFER_FRACTION + var/delta_carbon_dioxide = QUANTIZE(carbon_dioxide_archived - model.carbon_dioxide)/TRANSFER_FRACTION + var/delta_nitrogen = QUANTIZE(nitrogen_archived - model.nitrogen)/TRANSFER_FRACTION + var/delta_toxins = QUANTIZE(toxins_archived - model.toxins)/TRANSFER_FRACTION + + var/delta_temperature = (temperature_archived - model.temperature) + + var/heat_transferred = 0 + var/old_self_heat_capacity = 0 + var/heat_capacity_transferred = 0 + + if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) + + var/delta_air = delta_oxygen+delta_nitrogen + if(delta_air) + var/air_heat_capacity = SPECIFIC_HEAT_AIR*delta_air + heat_transferred -= air_heat_capacity*model.temperature + heat_capacity_transferred -= air_heat_capacity + + if(delta_carbon_dioxide) + var/carbon_dioxide_heat_capacity = SPECIFIC_HEAT_CDO*delta_carbon_dioxide + heat_transferred -= carbon_dioxide_heat_capacity*model.temperature + heat_capacity_transferred -= carbon_dioxide_heat_capacity + + if(delta_toxins) + var/toxins_heat_capacity = SPECIFIC_HEAT_TOXIN*delta_toxins + heat_transferred -= toxins_heat_capacity*model.temperature + heat_capacity_transferred -= toxins_heat_capacity + + old_self_heat_capacity = heat_capacity()*group_multiplier + + if(border_multiplier) + oxygen -= delta_oxygen*border_multiplier/group_multiplier + carbon_dioxide -= delta_carbon_dioxide*border_multiplier/group_multiplier + nitrogen -= delta_nitrogen*border_multiplier/group_multiplier + toxins -= delta_toxins*border_multiplier/group_multiplier + else + oxygen -= delta_oxygen/group_multiplier + carbon_dioxide -= delta_carbon_dioxide/group_multiplier + nitrogen -= delta_nitrogen/group_multiplier + toxins -= delta_toxins/group_multiplier + + var/moved_moles = (delta_oxygen + delta_carbon_dioxide + delta_nitrogen + delta_toxins) + + if(trace_gases.len) + for(var/datum/gas/trace_gas in trace_gases) + var/delta = 0 + + delta = trace_gas.moles_archived/TRANSFER_FRACTION + + if(border_multiplier) + trace_gas.moles -= delta*border_multiplier/group_multiplier + else + trace_gas.moles -= delta/group_multiplier + + var/heat_cap_transferred = delta*trace_gas.specific_heat + heat_transferred += heat_cap_transferred*temperature_archived + heat_capacity_transferred += heat_cap_transferred + moved_moles += delta + update_values() + + if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) + var/new_self_heat_capacity = old_self_heat_capacity - heat_capacity_transferred + if(new_self_heat_capacity > MINIMUM_HEAT_CAPACITY) + if(border_multiplier) + temperature = (old_self_heat_capacity*temperature - heat_capacity_transferred*border_multiplier*temperature_archived)/new_self_heat_capacity + else + temperature = (old_self_heat_capacity*temperature - heat_capacity_transferred*border_multiplier*temperature_archived)/new_self_heat_capacity + + temperature_mimic(model, model.thermal_conductivity, border_multiplier) + + if((delta_temperature > MINIMUM_TEMPERATURE_TO_MOVE) || abs(moved_moles) > MINIMUM_MOLES_DELTA_TO_MOVE) + var/delta_pressure = temperature_archived*(total_moles() + moved_moles) - model.temperature*(model.oxygen+model.carbon_dioxide+model.nitrogen+model.toxins) + return delta_pressure*R_IDEAL_GAS_EQUATION/volume + else + return 0 + +/datum/gas_mixture/proc/check_both_then_temperature_share(datum/gas_mixture/sharer, conduction_coefficient) + var/delta_temperature = (temperature_archived - sharer.temperature_archived) + + var/self_heat_capacity = heat_capacity_archived() + var/sharer_heat_capacity = sharer.heat_capacity_archived() + + var/self_temperature_delta = 0 + var/sharer_temperature_delta = 0 + + if((sharer_heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY)) + var/heat = conduction_coefficient*delta_temperature* \ + (self_heat_capacity*sharer_heat_capacity/(self_heat_capacity+sharer_heat_capacity)) + + self_temperature_delta = -heat/(self_heat_capacity*group_multiplier) + sharer_temperature_delta = heat/(sharer_heat_capacity*sharer.group_multiplier) + else + return 1 + + if((abs(self_temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) \ + && (abs(self_temperature_delta) > MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND*temperature_archived)) + return 0 + + if((abs(sharer_temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) \ + && (abs(sharer_temperature_delta) > MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND*sharer.temperature_archived)) + return -1 + + temperature += self_temperature_delta + sharer.temperature += sharer_temperature_delta + + return 1 + //Logic integrated from: temperature_share(sharer, conduction_coefficient) for efficiency + +/datum/gas_mixture/proc/check_me_then_temperature_share(datum/gas_mixture/sharer, conduction_coefficient) + var/delta_temperature = (temperature_archived - sharer.temperature_archived) + + var/self_heat_capacity = heat_capacity_archived() + var/sharer_heat_capacity = sharer.heat_capacity_archived() + + var/self_temperature_delta = 0 + var/sharer_temperature_delta = 0 + + if((sharer_heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY)) + var/heat = conduction_coefficient*delta_temperature* \ + (self_heat_capacity*sharer_heat_capacity/(self_heat_capacity+sharer_heat_capacity)) + + self_temperature_delta = -heat/(self_heat_capacity*group_multiplier) + sharer_temperature_delta = heat/(sharer_heat_capacity*sharer.group_multiplier) + else + return 1 + + if((abs(self_temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) \ + && (abs(self_temperature_delta) > MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND*temperature_archived)) + return 0 + + temperature += self_temperature_delta + sharer.temperature += sharer_temperature_delta + + return 1 + //Logic integrated from: temperature_share(sharer, conduction_coefficient) for efficiency + +/datum/gas_mixture/proc/check_me_then_temperature_turf_share(turf/simulated/sharer, conduction_coefficient) + var/delta_temperature = (temperature_archived - sharer.temperature) + + var/self_temperature_delta = 0 + var/sharer_temperature_delta = 0 + + if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) + var/self_heat_capacity = heat_capacity_archived() + + if((sharer.heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY)) + var/heat = conduction_coefficient*delta_temperature* \ + (self_heat_capacity*sharer.heat_capacity/(self_heat_capacity+sharer.heat_capacity)) + + self_temperature_delta = -heat/(self_heat_capacity*group_multiplier) + sharer_temperature_delta = heat/sharer.heat_capacity + else + return 1 + + if((abs(self_temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) \ + && (abs(self_temperature_delta) > MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND*temperature_archived)) + return 0 + + temperature += self_temperature_delta + sharer.temperature += sharer_temperature_delta + + return 1 + //Logic integrated from: temperature_turf_share(sharer, conduction_coefficient) for efficiency + +/datum/gas_mixture/proc/check_me_then_temperature_mimic(turf/model, conduction_coefficient) + var/delta_temperature = (temperature_archived - model.temperature) + var/self_temperature_delta = 0 + + if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) + var/self_heat_capacity = heat_capacity_archived() + + if((model.heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY)) + var/heat = conduction_coefficient*delta_temperature* \ + (self_heat_capacity*model.heat_capacity/(self_heat_capacity+model.heat_capacity)) + + self_temperature_delta = -heat/(self_heat_capacity*group_multiplier) + + if((abs(self_temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) \ + && (abs(self_temperature_delta) > MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND*temperature_archived)) + return 0 + + temperature += self_temperature_delta + + return 1 + //Logic integrated from: temperature_mimic(model, conduction_coefficient) for efficiency + +/datum/gas_mixture/proc/temperature_share(datum/gas_mixture/sharer, conduction_coefficient) + var/delta_temperature = (temperature_archived - sharer.temperature_archived) + if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) + var/self_heat_capacity = heat_capacity_archived() + var/sharer_heat_capacity = sharer.heat_capacity_archived() + if(!group_multiplier) + message_admins("Error! The gas mixture (ref \ref[src]) has no group multiplier!") + return + + if((sharer_heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY)) + var/heat = conduction_coefficient*delta_temperature* \ + (self_heat_capacity*sharer_heat_capacity/(self_heat_capacity+sharer_heat_capacity)) + + temperature -= heat/(self_heat_capacity*group_multiplier) + sharer.temperature += heat/(sharer_heat_capacity*sharer.group_multiplier) + +/datum/gas_mixture/proc/temperature_mimic(turf/model, conduction_coefficient, border_multiplier) + var/delta_temperature = (temperature - model.temperature) + if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) + var/self_heat_capacity = heat_capacity()//_archived() + if(!group_multiplier) + message_admins("Error! The gas mixture (ref \ref[src]) has no group multiplier!") + return + + if((model.heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY)) + var/heat = conduction_coefficient*delta_temperature* \ + (self_heat_capacity*model.heat_capacity/(self_heat_capacity+model.heat_capacity)) + + if(border_multiplier) + temperature -= heat*border_multiplier/(self_heat_capacity*group_multiplier) + else + temperature -= heat/(self_heat_capacity*group_multiplier) + +/datum/gas_mixture/proc/temperature_turf_share(turf/simulated/sharer, conduction_coefficient) + var/delta_temperature = (temperature_archived - sharer.temperature) + if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) + var/self_heat_capacity = heat_capacity() + + if((sharer.heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY)) + var/heat = conduction_coefficient*delta_temperature* \ + (self_heat_capacity*sharer.heat_capacity/(self_heat_capacity+sharer.heat_capacity)) + + temperature -= heat/(self_heat_capacity*group_multiplier) + sharer.temperature += heat/sharer.heat_capacity + +/datum/gas_mixture/proc/compare(datum/gas_mixture/sample) + //Purpose: Compares sample to self to see if within acceptable ranges that group processing may be enabled + //Called by: Airgroups trying to rebuild + //Inputs: Gas mix to compare + //Outputs: 1 if can rebuild, 0 if not. + if(!sample) return 0 + + if((abs(oxygen-sample.oxygen) > MINIMUM_AIR_TO_SUSPEND) && \ + ((oxygen < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.oxygen) || (oxygen > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.oxygen))) + return 0 + if((abs(nitrogen-sample.nitrogen) > MINIMUM_AIR_TO_SUSPEND) && \ + ((nitrogen < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.nitrogen) || (nitrogen > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.nitrogen))) + return 0 + if((abs(carbon_dioxide-sample.carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && \ + ((carbon_dioxide < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.carbon_dioxide) || (oxygen > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.carbon_dioxide))) + return 0 + if((abs(toxins-sample.toxins) > MINIMUM_AIR_TO_SUSPEND) && \ + ((toxins < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.toxins) || (toxins > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.toxins))) + return 0 + + if(total_moles() > MINIMUM_AIR_TO_SUSPEND) + if((abs(temperature-sample.temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) && \ + ((temperature < (1-MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND)*sample.temperature) || (temperature > (1+MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND)*sample.temperature))) + //world << "temp fail [temperature] & [sample.temperature]" + return 0 + + if(sample.trace_gases.len) + for(var/datum/gas/trace_gas in sample.trace_gases) + if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND) + var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases + if(corresponding) + if((abs(trace_gas.moles - corresponding.moles) > MINIMUM_AIR_TO_SUSPEND) && \ + ((corresponding.moles < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*trace_gas.moles) || (corresponding.moles > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*trace_gas.moles))) + return 0 + else + return 0 + + if(trace_gases.len) + for(var/datum/gas/trace_gas in trace_gases) + if(trace_gas.moles > MINIMUM_AIR_TO_SUSPEND) + var/datum/gas/corresponding = locate(trace_gas.type) in sample.trace_gases + if(corresponding) + if((abs(trace_gas.moles - corresponding.moles) > MINIMUM_AIR_TO_SUSPEND) && \ + ((trace_gas.moles < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*corresponding.moles) || (trace_gas.moles > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*corresponding.moles))) + return 0 + else + return 0 + return 1 + +/datum/gas_mixture/proc/subtract(datum/gas_mixture/right_side) + //Purpose: Subtracts right_side from air_mixture. Used to help turfs mingle + //Called by: Pipelines ending in a break (or something) + //Inputs: Gas mix to remove + //Outputs: 1 + + oxygen -= right_side.oxygen + carbon_dioxide -= right_side.carbon_dioxide + nitrogen -= right_side.nitrogen + toxins -= right_side.toxins + + if((trace_gases.len > 0)||(right_side.trace_gases.len > 0)) + for(var/datum/gas/trace_gas in right_side.trace_gases) + var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases + if(!corresponding) + corresponding = new trace_gas.type() + trace_gases += corresponding + + corresponding.moles -= trace_gas.moles + update_values() + return 1 \ No newline at end of file diff --git a/code/ZAS - vgstation/FEA_system.dm b/code/ZAS - vg/FEA_system.dm similarity index 100% rename from code/ZAS - vgstation/FEA_system.dm rename to code/ZAS - vg/FEA_system.dm diff --git a/code/ZAS - vgstation/Fire.dm b/code/ZAS - vg/Fire.dm similarity index 65% rename from code/ZAS - vgstation/Fire.dm rename to code/ZAS - vg/Fire.dm index 5d0ab4b0f17..6909ccd213d 100644 --- a/code/ZAS - vgstation/Fire.dm +++ b/code/ZAS - vg/Fire.dm @@ -43,148 +43,142 @@ turf/simulated/hotspot_expose(exposed_temperature, exposed_volume, soh) return igniting -obj - fire - //Icon for fire on turfs. +/obj/fire + //Icon for fire on turfs. - anchored = 1 - mouse_opacity = 0 + anchored = 1 + mouse_opacity = 0 - //luminosity = 3 + //luminosity = 3 - icon = 'icons/effects/fire.dmi' + icon = 'icons/effects/fire.dmi' + icon_state = "1" + + layer = TURF_LAYER + + var/firelevel = 10000 //Calculated by gas_mixture.calculate_firelevel() + +/obj/fire/process() + . = 1 + + //get location and check if it is in a proper ZAS zone + var/turf/simulated/S = loc + + if(!istype(S)) + del src + + if(!S.zone) + del src + + var/datum/gas_mixture/air_contents = S.return_air() + //get liquid fuels on the ground. + var/obj/effect/decal/cleanable/liquid_fuel/liquid = locate() in S + //and the volatile stuff from the air + var/datum/gas/volatile_fuel/fuel = locate() in air_contents.trace_gases + + //since the air is processed in fractions, we need to make sure not to have any minuscle residue or + //the amount of moles might get to low for some functions to catch them and thus result in wonky behaviour + if(air_contents.oxygen < 0.001) + air_contents.oxygen = 0 + if(air_contents.toxins < 0.001) + air_contents.toxins = 0 + if(fuel) + if(fuel.moles < 0.001) + air_contents.trace_gases.Remove(fuel) + + //check if there is something to combust + if(!air_contents.check_recombustability(liquid)) + //del src + RemoveFire() + + //get a firelevel and set the icon + firelevel = air_contents.calculate_firelevel(liquid) + + if(firelevel > 6) + icon_state = "3" + SetLuminosity(7) + else if(firelevel > 2.5) + icon_state = "2" + SetLuminosity(5) + else icon_state = "1" + SetLuminosity(3) - layer = TURF_LAYER + //im not sure how to implement a version that works for every creature so for now monkeys are firesafe + for(var/mob/living/carbon/human/M in loc) + M.FireBurn(firelevel, air_contents.temperature, air_contents.return_pressure() ) //Burn the humans! + for(var/atom/A in loc) + A.fire_act(air_contents, air_contents.temperature, air_contents.return_volume()) + //spread + for(var/direction in cardinal) + if(S.air_check_directions&direction) //Grab all valid bordering tiles - var - firelevel = 10000 //Calculated by gas_mixture.calculate_firelevel() + var/turf/simulated/enemy_tile = get_step(S, direction) - process() - . = 1 + if(istype(enemy_tile)) + var/datum/gas_mixture/acs = enemy_tile.return_air() + var/obj/effect/decal/cleanable/liquid_fuel/liq = locate() in enemy_tile + if(!acs) continue + if(!acs.check_recombustability(liq)) continue + //If extinguisher mist passed over the turf it's trying to spread to, don't spread and + //reduce firelevel. + if(enemy_tile.fire_protection > world.time-30) + firelevel -= 1.5 + continue - //get location and check if it is in a proper ZAS zone - var/turf/simulated/S = loc + //Spread the fire. + if(!(locate(/obj/fire) in enemy_tile)) + if( prob( 50 + 50 * (firelevel/zas_settings.Get(/datum/ZAS_Setting/fire_firelevel_multiplier)) ) && S.CanPass(null, enemy_tile, 0,0) && enemy_tile.CanPass(null, S, 0,0)) + new/obj/fire(enemy_tile,firelevel) - if(!istype(S)) - src.gc_del() - - if(!S.zone) - src.gc_del() - - var/datum/gas_mixture/air_contents = S.return_air() - //get liquid fuels on the ground. - var/obj/effect/decal/cleanable/liquid_fuel/liquid = locate() in S - //and the volatile stuff from the air - var/datum/gas/volatile_fuel/fuel = locate() in air_contents.trace_gases - - //since the air is processed in fractions, we need to make sure not to have any minuscle residue or - //the amount of moles might get to low for some functions to catch them and thus result in wonky behaviour - if(air_contents.oxygen < 0.001) - air_contents.oxygen = 0 - if(air_contents.toxins < 0.001) - air_contents.toxins = 0 - if(fuel) - if(fuel.moles < 0.001) - air_contents.trace_gases.Remove(fuel) - - //check if there is something to combust - if(!air_contents.check_recombustability(liquid)) - //src.gc_del() - RemoveFire() - - //get a firelevel and set the icon - firelevel = air_contents.calculate_firelevel(liquid) - - if(firelevel > 6) - icon_state = "3" - SetLuminosity(7) - else if(firelevel > 2.5) - icon_state = "2" - SetLuminosity(5) - else - icon_state = "1" - SetLuminosity(3) - - //im not sure how to implement a version that works for every creature so for now monkeys are firesafe - for(var/mob/living/carbon/human/M in loc) - M.FireBurn(firelevel, air_contents.temperature, air_contents.return_pressure() ) //Burn the humans! - for(var/atom/A in loc) - A.fire_act(air_contents, air_contents.temperature, air_contents.return_volume()) - //spread - for(var/direction in cardinal) - if(S.air_check_directions&direction) //Grab all valid bordering tiles - - var/turf/simulated/enemy_tile = get_step(S, direction) - - if(istype(enemy_tile)) - var/datum/gas_mixture/acs = enemy_tile.return_air() - var/obj/effect/decal/cleanable/liquid_fuel/liq = locate() in enemy_tile - if(!acs) continue - if(!acs.check_recombustability(liq)) continue - //If extinguisher mist passed over the turf it's trying to spread to, don't spread and - //reduce firelevel. - if(enemy_tile.fire_protection > world.time-30) - firelevel -= 1.5 - continue - - //Spread the fire. - if(!(locate(/obj/fire) in enemy_tile)) - if( prob( 50 + 50 * (firelevel/zas_settings.Get(/datum/ZAS_Setting/fire_firelevel_multiplier)) ) && S.CanPass(null, enemy_tile, 0,0) && enemy_tile.CanPass(null, S, 0,0)) - new/obj/fire(enemy_tile,firelevel) - - //seperate part of the present gas - //this is done to prevent the fire burning all gases in a single pass - var/datum/gas_mixture/flow = air_contents.remove_ratio(zas_settings.Get(/datum/ZAS_Setting/fire_consumption_rate)) + //seperate part of the present gas + //this is done to prevent the fire burning all gases in a single pass + var/datum/gas_mixture/flow = air_contents.remove_ratio(zas_settings.Get(/datum/ZAS_Setting/fire_consumption_rate)) ///////////////////////////////// FLOW HAS BEEN CREATED /// DONT DELETE THE FIRE UNTIL IT IS MERGED BACK OR YOU WILL DELETE AIR /////////////////////////////////////////////// - if(flow) + if(flow) - if(flow.check_recombustability(liquid)) - //Ensure flow temperature is higher than minimum fire temperatures. - //this creates some energy ex nihilo but is necessary to get a fire started - //lets just pretend this energy comes from the ignition source and dont mention this again - //flow.temperature = max(PLASMA_MINIMUM_BURN_TEMPERATURE+0.1,flow.temperature) + if(flow.check_recombustability(liquid)) + //Ensure flow temperature is higher than minimum fire temperatures. + //this creates some energy ex nihilo but is necessary to get a fire started + //lets just pretend this energy comes from the ignition source and dont mention this again + //flow.temperature = max(PLASMA_MINIMUM_BURN_TEMPERATURE+0.1,flow.temperature) - //burn baby burn! + //burn baby burn! - flow.zburn(liquid,1) - //merge the air back - S.assume_air(flow) + flow.zburn(liquid,1) + //merge the air back + S.assume_air(flow) -///////////////////////////////// FLOW HAS BEEN REMERGED /// feel free to delete the fire again from here on ///////////////////////////////////////////////////////////////// +///////////////////////////////// FLOW HAS BEEN REMERGED /// feel free to delete the fire again from here on ////////////////////////////////////////////////////////////////// - New(newLoc,fl) - ..() +/obj/fire/New(newLoc,fl) + ..() - if(!istype(loc, /turf)) - src.gc_del() + if(!istype(loc, /turf)) + del src - dir = pick(cardinal) - SetLuminosity(3) - firelevel = fl - air_master.active_hotspots.Add(src) + dir = pick(cardinal) + SetLuminosity(3) + firelevel = fl + air_master.active_hotspots.Add(src) - Del() - if (istype(loc, /turf/simulated)) - SetLuminosity(0) +/obj/fire/Del() + if (istype(loc, /turf/simulated)) + SetLuminosity(0) - loc = null - air_master.active_hotspots.Remove(src) + loc = null + air_master.active_hotspots.Remove(src) - ..() + ..() - proc/RemoveFire() - if (istype(loc, /turf/simulated)) - SetLuminosity(0) - loc = null - air_master.active_hotspots.Remove(src) - - proc/gc_del() - loc = null - air_master.active_hotspots.Remove(src) +/obj/fire/proc/RemoveFire() + if (istype(loc, /turf/simulated)) + SetLuminosity(0) + loc = null + air_master.active_hotspots.Remove(src) diff --git a/code/ZAS - vgstation/Functions.dm b/code/ZAS - vg/Functions.dm similarity index 98% rename from code/ZAS - vgstation/Functions.dm rename to code/ZAS - vg/Functions.dm index dc8f2c2a591..ce24513418e 100644 --- a/code/ZAS - vgstation/Functions.dm +++ b/code/ZAS - vg/Functions.dm @@ -78,7 +78,7 @@ proc/FloodFill(turf/simulated/start) proc/ZMerge(zone/A,zone/B) //Sanity~ - if(!istype(A) || !istype(B) || !istype(B.air) || !istype(A.air)) + if(!istype(A) || !istype(B)) return var/new_contents = A.contents + B.contents diff --git a/code/ZAS/NewSettings.dm b/code/ZAS - vg/NewSettings.dm similarity index 100% rename from code/ZAS/NewSettings.dm rename to code/ZAS - vg/NewSettings.dm diff --git a/code/ZAS - vgstation/Plasma.dm b/code/ZAS - vg/Plasma.dm similarity index 84% rename from code/ZAS - vgstation/Plasma.dm rename to code/ZAS - vg/Plasma.dm index a7bd605c86b..5936f3843b0 100644 --- a/code/ZAS - vgstation/Plasma.dm +++ b/code/ZAS - vg/Plasma.dm @@ -2,22 +2,22 @@ var/image/contamination_overlay = image('icons/effects/contamination.dmi') obj/var/contaminated = 0 -obj/item/proc - can_contaminate() - //Clothing and backpacks can be contaminated. - if(flags & PLASMAGUARD) return 0 - else if(istype(src,/obj/item/weapon/storage/backpack)) return 0 //Cannot be washed :( - else if(istype(src,/obj/item/clothing)) return 1 - contaminate() - //Do a contamination overlay? Temporary measure to keep contamination less deadly than it was. - if(!contaminated) - contaminated = 1 - overlays += contamination_overlay +/obj/item/proc/can_contaminate() + //Clothing and backpacks can be contaminated. + if(flags & PLASMAGUARD) return 0 + else if(istype(src,/obj/item/weapon/storage/backpack)) return 0 //Cannot be washed :( + else if(istype(src,/obj/item/clothing)) return 1 - decontaminate() - contaminated = 0 - overlays -= contamination_overlay +/obj/item/proc/contaminate() + //Do a contamination overlay? Temporary measure to keep contamination less deadly than it was. + if(!contaminated) + contaminated = 1 + overlays += contamination_overlay + +/obj/item/proc/decontaminate() + contaminated = 0 + overlays -= contamination_overlay /mob/proc/contaminate() diff --git a/code/ZAS - vgstation/Variable Settings.dm b/code/ZAS - vg/Variable Settings.dm similarity index 100% rename from code/ZAS - vgstation/Variable Settings.dm rename to code/ZAS - vg/Variable Settings.dm diff --git a/code/ZAS - vg/ZAS_Turfs.dm b/code/ZAS - vg/ZAS_Turfs.dm new file mode 100644 index 00000000000..e7f5f4402f8 --- /dev/null +++ b/code/ZAS - vg/ZAS_Turfs.dm @@ -0,0 +1,394 @@ +/atom/var/pressure_resistance = ONE_ATMOSPHERE + +/turf/var/zone/zone + +/turf/assume_air(datum/gas_mixture/giver) //use this for machines to adjust air + del(giver) + return 0 + +/turf/return_air() + //Create gas mixture to hold data for passing + var/datum/gas_mixture/GM = new + + GM.oxygen = oxygen + GM.carbon_dioxide = carbon_dioxide + GM.nitrogen = nitrogen + GM.toxins = toxins + + GM.temperature = temperature + GM.update_values() + + return GM + +// For new turfs +/turf/proc/copy_air_from(var/turf/T) + oxygen = T.oxygen + carbon_dioxide = T.carbon_dioxide + nitrogen = T.nitrogen + toxins = T.toxins + + temperature = T.temperature + +/turf/remove_air(amount as num) + var/datum/gas_mixture/GM = new + + var/sum = oxygen + carbon_dioxide + nitrogen + toxins + if(sum>0) + GM.oxygen = (oxygen/sum)*amount + GM.carbon_dioxide = (carbon_dioxide/sum)*amount + GM.nitrogen = (nitrogen/sum)*amount + GM.toxins = (toxins/sum)*amount + + GM.temperature = temperature + GM.update_values() + + return GM + +/turf/simulated/var/current_graphic = null +/turf/simulated/var/tmp/datum/gas_mixture/air +/turf/simulated/var/tmp/processing = 1 +/turf/simulated/var/tmp/air_check_directions = 0 //Do not modify this, just add turf to air_master.tiles_to_update +/turf/simulated/var/tmp/obj/fire/active_hotspot +/turf/simulated/var/tmp/was_icy=0 + +/turf/simulated/proc/update_visuals() + overlays = null + + var/siding_icon_state = return_siding_icon_state() + if(siding_icon_state) + overlays += image('icons/turf/floors.dmi',siding_icon_state) + + // ONLY USED IF ZAS_SETTINGS SAYS SO. + var/datum/gas_mixture/model = return_air() + if(model.graphics & GRAPHICS_COLD) + if(!was_icy) + wet=3 // Custom ice + was_icy=1 + var/o="" + //if(is_plating()) + // o="snowfloor_s" + //else + if(is_plasteel_floor()) + o="snowfloor" + if(o!="") + overlays += image('icons/turf/overlays.dmi',o) + else + if(was_icy) + wet=0 + was_icy=0 + if(prob(10)) + wet = 1 + if(wet_overlay) + overlays -= wet_overlay + wet_overlay = null + wet_overlay = image('icons/effects/water.dmi',src,"wet_floor") + overlays += wet_overlay + + spawn(800) + if (!istype(src)) return + if(wet >= 2) return + wet = 0 + if(wet_overlay) + overlays -= wet_overlay + wet_overlay = null + if(model.graphics & GRAPHICS_PLASMA) + overlays.Add(plmaster) + if(model.graphics & GRAPHICS_N2O) + overlays.Add(slmaster) + //if(model.graphics & GRAPHICS_REAGENTS) + // overlays.Add(slmaster/*rlmaster*/) + + +/turf/simulated/New() + ..() + + if(!blocks_air) + air = new + + air.oxygen = oxygen + air.carbon_dioxide = carbon_dioxide + air.nitrogen = nitrogen + air.toxins = toxins + + air.temperature = temperature + air.update_values() + + if(air_master) + air_master.tiles_to_update.Add(src) + + else + if(air_master) + for(var/direction in cardinal) + var/turf/simulated/floor/target = get_step(src,direction) + if(istype(target)) + air_master.tiles_to_update |= target + +/turf/simulated/Del() + if(active_hotspot) + del(active_hotspot) + if(blocks_air) + for(var/direction in list(NORTH, SOUTH, EAST, WEST)) + var/turf/simulated/tile = get_step(src,direction) + if(istype(tile) && !tile.blocks_air) + air_master.tiles_to_update.Add(tile) + ..() + +/turf/simulated/copy_air_from(var/turf/T) + //if(istype(T,/turf/simulated)) + // var/turf/simulated/ST=T + // air=ST.air + air=T.return_air() + +/turf/simulated/assume_air(datum/gas_mixture/giver) + if(!giver) return 0 + if(zone) + zone.air.merge(giver) + return 1 + else + return ..() + +/turf/simulated/return_air() + if(zone) + return zone.air + else if(air) + return air + + else + return ..() + +/turf/simulated/remove_air(amount as num) + if(zone) + var/datum/gas_mixture/removed = null + removed = zone.air.remove(amount) + if(zone.air.check_tile_graphic()) + update_visuals(zone.air) + return removed + else if(air) + var/datum/gas_mixture/removed = null + removed = air.remove(amount) + + if(air.check_tile_graphic()) + update_visuals(air) + return removed + + else + return ..() + +/turf/simulated/proc/update_air_properties() + var/air_directions_archived = air_check_directions + air_check_directions = 0 + + for(var/direction in cardinal) + if(ZAirPass(get_step(src,direction))) + air_check_directions |= direction + + if(!zone && !blocks_air) //No zone, but not a wall. + for(var/direction in DoorDirections) //Check door directions first. + if(air_check_directions&direction) + var/turf/simulated/T = get_step(src,direction) + if(!istype(T)) + continue + if(T.zone) + T.zone.AddTurf(src) + break + if(!zone) //Still no zone + for(var/direction in CounterDoorDirections) //Check the others second. + if(air_check_directions&direction) + var/turf/simulated/T = get_step(src,direction) + if(!istype(T)) + continue + if(T.zone) + T.zone.AddTurf(src) + break + if(!zone) //No zone found, new zone! + new/zone(src) + if(!zone) //Still no zone, the floodfill determined it is not part of a larger zone. Force a zone on it. + new/zone(list(src)) + + //Check pass sanity of the connections. + if("\ref[src]" in air_master.turfs_with_connections) + for(var/connection/C in air_master.turfs_with_connections["\ref[src]"]) + air_master.connections_to_check |= C + + if(zone && !zone.rebuild) + if(zone.air.check_tile_graphic()) + update_visuals(zone.air) + for(var/direction in cardinal) + var/turf/T = get_step(src,direction) + if(!istype(T)) + continue + + //I can connect to air in this direction + if(air_check_directions&direction) + + //If either block air, we must look to see if the adjacent turfs need rebuilt. + if(!CanPass(null, T, 0, 0)) + + //Target blocks air + if(!T.CanPass(null, T, 0, 0)) + var/turf/NT = get_step(T, direction) + + //If that turf is in my zone still, rebuild. + if(istype(NT,/turf/simulated) && NT in zone.contents) + zone.rebuild = 1 + + //If that is an unsimulated tile in my zone, see if we need to rebuild or just remove. + else if(istype(NT) && NT in zone.unsimulated_tiles) + var/consider_rebuild = 0 + for(var/d in cardinal) + var/turf/UT = get_step(NT,d) + if(istype(UT, /turf/simulated) && UT.zone == zone && UT.CanPass(null, NT, 0, 0)) //If we find a neighboring tile that is in the same zone, check if we need to rebuild + consider_rebuild = 1 + break + if(consider_rebuild) + zone.rebuild = 1 //Gotta check if we need to rebuild, dammit + else + zone.RemoveTurf(NT) //Not adjacent to anything, and unsimulated. Goodbye~ + + //To make a closed connection through closed door. + ZConnect(T, src) + + //If I block air. + else if(T.zone && !T.zone.rebuild) + var/turf/NT = get_step(src, reverse_direction(direction)) + + //If I am splitting a zone, rebuild. + if(istype(NT,/turf/simulated) && (NT in T.zone.contents || (NT.zone && T in NT.zone.contents))) + T.zone.rebuild = 1 + + //If NT is unsimulated, parse if I should remove it or rebuild. + else if(istype(NT) && NT in T.zone.unsimulated_tiles) + var/consider_rebuild = 0 + for(var/d in cardinal) + var/turf/UT = get_step(NT,d) + if(istype(UT, /turf/simulated) && UT.zone == T.zone && UT.CanPass(null, NT, 0, 0)) //If we find a neighboring tile that is in the same zone, check if we need to rebuild + consider_rebuild = 1 + break + + //Needs rebuilt. + if(consider_rebuild) + T.zone.rebuild = 1 + + //Not adjacent to anything, and unsimulated. Goodbye~ + else + T.zone.RemoveTurf(NT) + + else + //Produce connection through open door. + ZConnect(src,T) + + //Something like a wall was built, changing the geometry. + else if(air_directions_archived&direction) + var/turf/NT = get_step(T, direction) + + //If the tile is in our own zone, and we cannot connect to it, better rebuild. + if(istype(NT,/turf/simulated) && NT in zone.contents) + zone.rebuild = 1 + + //Parse if we need to remove the tile, or rebuild the zone. + else if(istype(NT) && NT in zone.unsimulated_tiles) + var/consider_rebuild = 0 + + //Loop through all neighboring turfs to see if we should remove the turf or just rebuild. + for(var/d in cardinal) + var/turf/UT = get_step(NT,d) + + //If we find a neighboring tile that is in the same zone, rebuild + if(istype(UT, /turf/simulated) && UT.zone == zone && UT.CanPass(null, NT, 0, 0)) + consider_rebuild = 1 + break + + //The unsimulated turf is adjacent to another one of our zone's turfs, + // better rebuild to be sure we didn't get cut in twain + if(consider_rebuild) + zone.rebuild = 1 + + //Not adjacent to anything, and unsimulated. Goodbye~ + else + zone.RemoveTurf(NT) + + if(air_check_directions) + processing = 1 + else + processing = 0 + return 1 + +/turf/proc/HasDoor(turf/O) + //Checks for the presence of doors, used for zone spreading and connection. + //A positive numerical argument checks only for closed doors. + //Another turf as an argument checks for windoors between here and there. + for(var/obj/machinery/door/D in src) + if(isnum(O) && O) + if(!D.density) continue + if(istype(D,/obj/machinery/door/window)) + if(!istype(O)) + continue + if(D.dir == get_dir(D,O)) + return 1 + else + return 1 + +/turf/proc/ZCanPass(turf/simulated/T, var/include_space = 0) + //Fairly standard pass checks for turfs, objects and directional windows. Also stops at the edge of space. + if(!istype(T)) + return 0 + + if(!istype(T) && !include_space) + return 0 + else + if(T.blocks_air||blocks_air) + return 0 + + for(var/obj/obstacle in src) + if(istype(obstacle, /obj/machinery/door) && !obstacle:air_properties_vary_with_direction) + continue + if(!obstacle.CanPass(null, T, 1.5, 1)) + return 0 + + for(var/obj/obstacle in T) + if(istype(obstacle, /obj/machinery/door) && !obstacle:air_properties_vary_with_direction) + continue + if(!obstacle.CanPass(null, src, 1.5, 1)) + return 0 + + return 1 + +/turf/proc/ZAirPass(turf/T) + //Fairly standard pass checks for turfs, objects and directional windows. + if(!istype(T)) + return 0 + + if(T.blocks_air||blocks_air) + return 0 + + for(var/obj/obstacle in src) + if(istype(obstacle, /obj/machinery/door) && !obstacle:air_properties_vary_with_direction) + continue + if(!obstacle.CanPass(null, T, 0, 0)) + return 0 + + for(var/obj/obstacle in T) + if(istype(obstacle, /obj/machinery/door) && !obstacle:air_properties_vary_with_direction) + continue + if(!obstacle.CanPass(null, src, 0, 0)) + return 0 + + return 1 + +/*UNUSED +/turf/proc/check_connections() + //Checks for new connections that can be made. + for(var/d in cardinal) + var/turf/simulated/T = get_step(src,d) + if(istype(T) && ( !T.zone || !T.CanPass(0,src,0,0) ) ) + continue + if(T.zone != zone) + ZConnect(src,T) + +/turf/proc/check_for_space() + //Checks for space around the turf. + for(var/d in cardinal) + var/turf/T = get_step(src,d) + if(istype(T,/turf/space) && T.CanPass(0,src,0,0)) + zone.AddSpace(T) + */ \ No newline at end of file diff --git a/code/ZAS - vgstation/ZAS_Zones.dm b/code/ZAS - vg/ZAS_Zones.dm similarity index 95% rename from code/ZAS - vgstation/ZAS_Zones.dm rename to code/ZAS - vg/ZAS_Zones.dm index a90a699afca..c538a6c7c2a 100644 --- a/code/ZAS - vgstation/ZAS_Zones.dm +++ b/code/ZAS - vg/ZAS_Zones.dm @@ -178,24 +178,28 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs //Check the graphic. progress = "problem with: modifying turf graphics" - air.graphic = 0 + air.graphics = 0 if(air.toxins > MOLES_PLASMA_VISIBLE) - air.graphic = 1 - else if(air.trace_gases.len) + air.graphics |= GRAPHICS_PLASMA + if(air.trace_gases.len) var/datum/gas/sleeping_agent = locate(/datum/gas/sleeping_agent) in air.trace_gases if(sleeping_agent && (sleeping_agent.moles > 1)) - air.graphic = 2 + air.graphics |= GRAPHICS_N2O + // If configured and cold, maek ice + if(zas_settings.Get(/datum/ZAS_Setting/ice_formation)) + if(air.temperature <= TEMPERATURE_ICE_FORMATION && air.return_pressure()>MIN_PRESSURE_ICE_FORMATION) + air.graphics |= GRAPHICS_COLD progress = "problem with an inbuilt byond function: some conditional checks" //Only run through the individual turfs if there's reason to. - if(air.graphic != air.graphic_archived || air.temperature > PLASMA_FLASHPOINT) + if(air.graphics != air.graphics_archived || air.temperature > PLASMA_FLASHPOINT) progress = "problem with: turf/simulated/update_visuals()" for(var/turf/simulated/S in contents) //Update overlays. - if(air.graphic != air.graphic_archived) + if(air.graphics != air.graphics_archived) if(S.HasDoor(1)) S.update_visuals() else @@ -212,7 +216,7 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs progress = "problem with: calculating air graphic" //Archive graphic so we can know if it's different. - air.graphic_archived = air.graphic + air.graphics_archived = air.graphics progress = "problem with: calculating air temp" @@ -276,7 +280,7 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs //Air Movement// //////////////// -var/list/sharing_lookup_table = list(0.03, 0.07, 0.11, 0.15, 0.18, 0.20) +var/list/sharing_lookup_table = list(0.30, 0.40, 0.48, 0.54, 0.60, 0.66) proc/ShareRatio(datum/gas_mixture/A, datum/gas_mixture/B, connecting_tiles) //Shares a specific ratio of gas between mixtures using simple weighted averages. @@ -407,15 +411,15 @@ proc/ShareSpace(datum/gas_mixture/A, list/unsimulated_tiles, dbg_output) if(sharing_lookup_table.len >= unsimulated_tiles.len) //6 or more interconnecting tiles will max at 42% of air moved per tick. ratio = sharing_lookup_table[unsimulated_tiles.len] - //We need to adjust it to account for the insulation settings. - ratio *= 1 - zas_settings.Get(/datum/ZAS_Setting/connection_insulation) - A.oxygen = max(0, (A.oxygen - oxy_avg) * (1 - ratio) + oxy_avg ) A.nitrogen = max(0, (A.nitrogen - nit_avg) * (1 - ratio) + nit_avg ) A.carbon_dioxide = max(0, (A.carbon_dioxide - co2_avg) * (1 - ratio) + co2_avg ) A.toxins = max(0, (A.toxins - plasma_avg) * (1 - ratio) + plasma_avg ) - A.temperature = max(TCMB, (A.temperature - temp_avg) * (1 - ratio) + temp_avg ) + // EXPERIMENTAL: Disable space being cold + // N3X: Made this togglable for Pomf. Comment recovered from older code. + if(!zas_settings.Get(/datum/ZAS_Setting/space_isnt_cold)) + A.temperature = max(TCMB, (A.temperature - temp_avg) * (1 - ratio) + temp_avg ) for(var/datum/gas/G in A.trace_gases) var/G_avg = (G.moles * size) / (size + share_size) @@ -444,6 +448,9 @@ proc/ShareHeat(datum/gas_mixture/A, datum/gas_mixture/B, connecting_tiles) ratio = sharing_lookup_table[connecting_tiles] //WOOT WOOT TOUCH THIS AND YOU ARE A RETARD + //We need to adjust it to account for the insulation settings. + ratio *= 1 - zas_settings.Get(/datum/ZAS_Setting/connection_insulation) + A.temperature = max(0, (A.temperature - temp_avg) * (1- (ratio / max(1,A.group_multiplier)) ) + temp_avg ) B.temperature = max(0, (B.temperature - temp_avg) * (1- (ratio / max(1,B.group_multiplier)) ) + temp_avg ) diff --git a/code/ZAS - vgstation/FEA_gas_mixture.dm b/code/ZAS - vgstation/FEA_gas_mixture.dm deleted file mode 100644 index a4104ab01c7..00000000000 --- a/code/ZAS - vgstation/FEA_gas_mixture.dm +++ /dev/null @@ -1,1038 +0,0 @@ -/* -What are the archived variables for? - Calculations are done using the archived variables with the results merged into the regular variables. - This prevents race conditions that arise based on the order of tile processing. -*/ - -#define SPECIFIC_HEAT_TOXIN 200 -#define SPECIFIC_HEAT_AIR 20 -#define SPECIFIC_HEAT_CDO 30 -#define HEAT_CAPACITY_CALCULATION(oxygen,carbon_dioxide,nitrogen,toxins) \ - (carbon_dioxide*SPECIFIC_HEAT_CDO + (oxygen+nitrogen)*SPECIFIC_HEAT_AIR + toxins*SPECIFIC_HEAT_TOXIN) - -#define MINIMUM_HEAT_CAPACITY 0.0003 -#define QUANTIZE(variable) (round(variable,0.0001)) -#define TRANSFER_FRACTION 5 //What fraction (1/#) of the air difference to try and transfer - -datum - gas //These are used for the "Trace Gases" stuff, but is buggy. - sleeping_agent - specific_heat = 40 - - oxygen_agent_b - specific_heat = 300 - - volatile_fuel - specific_heat = 30 - - var - moles = 0 - specific_heat = 0 - - moles_archived = 0 - - gas_mixture - var //Holds the "moles" of each of the four gases. - oxygen = 0 - carbon_dioxide = 0 - nitrogen = 0 - toxins = 0 - total_moles = 0 //Updated when a reaction occurs. - - volume = CELL_VOLUME - - temperature = 0 //in Kelvin, use calculate_temperature() to modify - - group_multiplier = 1 - //Size of the group this gas_mixture is representing. - //=1 for singletons - - graphic - - list/datum/gas/trace_gases = list() //Seemed to be a good idea that was abandoned - - tmp //These are variables for use with the archived data - oxygen_archived - carbon_dioxide_archived - nitrogen_archived - toxins_archived - - temperature_archived - - graphic_archived = 0 - fuel_burnt = 0 - -//FOR THE LOVE OF GOD PLEASE USE THIS PROC -//Call it with negative numbers to remove gases. - - proc/adjust(o2 = 0, co2 = 0, n2 = 0, tx = 0, list/datum/gas/traces = list()) - //Purpose: Adjusting the gases within a airmix - //Called by: Nothing, yet! - //Inputs: The values of the gases to adjust - //Outputs: null - - oxygen = max(0, oxygen + o2) - carbon_dioxide = max(0, carbon_dioxide + co2) - nitrogen = max(0, nitrogen + n2) - toxins = max(0, toxins + tx) - - //handle trace gasses - for(var/datum/gas/G in traces) - var/datum/gas/T = locate(G.type) in trace_gases - if(T) - T.moles = max(G.moles + T.moles, 0) - else if(G.moles > 0) - trace_gases |= G - update_values() - return - - //tg seems to like using these a lot - proc/return_temperature() - return temperature - - - proc/return_volume() - return max(0, volume) - - - proc/thermal_energy() - return temperature*heat_capacity() - -/////////////////////////////// -//PV=nRT - related procedures// -/////////////////////////////// - - - proc/heat_capacity() - //Purpose: Returning the heat capacity of the gas mix - //Called by: UNKNOWN - //Inputs: None - //Outputs: Heat capacity - - var/heat_capacity = HEAT_CAPACITY_CALCULATION(oxygen,carbon_dioxide,nitrogen,toxins) - - if(trace_gases.len) - for(var/datum/gas/trace_gas in trace_gases) - heat_capacity += trace_gas.moles*trace_gas.specific_heat - - return max(MINIMUM_HEAT_CAPACITY,heat_capacity) - - proc/heat_capacity_archived() - //Purpose: Returning the archived heat capacity of the gas mix - //Called by: UNKNOWN - //Inputs: None - //Outputs: Archived heat capacity - - var/heat_capacity_archived = HEAT_CAPACITY_CALCULATION(oxygen_archived,carbon_dioxide_archived,nitrogen_archived,toxins_archived) - - if(trace_gases.len) - for(var/datum/gas/trace_gas in trace_gases) - heat_capacity_archived += trace_gas.moles_archived*trace_gas.specific_heat - - return max(MINIMUM_HEAT_CAPACITY,heat_capacity_archived) - - proc/total_moles() - return total_moles - /*var/moles = oxygen + carbon_dioxide + nitrogen + toxins - - if(trace_gases.len) - for(var/datum/gas/trace_gas in trace_gases) - moles += trace_gas.moles - return moles*/ - - proc/return_pressure() - //Purpose: Calculating Current Pressure - //Called by: - //Inputs: None - //Outputs: Gas pressure. - - if(volume>0) - return total_moles()*R_IDEAL_GAS_EQUATION*temperature/volume - return 0 - -// proc/return_temperature() - //Purpose: - //Inputs: - //Outputs: - -// return temperature - -// proc/return_volume() - //Purpose: - //Inputs: - //Outputs: - -// return max(0, volume) - -// proc/thermal_energy() - //Purpose: - //Inputs: - //Outputs: - -// return temperature*heat_capacity() - - proc/update_values() - //Purpose: Calculating and storing values which were normally called CONSTANTLY - //Called by: Anything that changes values within a gas mix. - //Inputs: None - //Outputs: None - - total_moles = oxygen + carbon_dioxide + nitrogen + toxins - - if(trace_gases.len) - for(var/datum/gas/trace_gas in trace_gases) - total_moles += trace_gas.moles - - return - -//////////////////////////////////////////// -//Procedures used for very specific events// -//////////////////////////////////////////// - - - proc/check_tile_graphic() - //Purpose: Calculating the graphic for a tile - //Called by: Turfs updating - //Inputs: None - //Outputs: 1 if graphic changed, 0 if unchanged - - graphic = 0 - if(toxins > MOLES_PLASMA_VISIBLE) - graphic = 1 - else if(length(trace_gases)) - var/datum/gas/sleeping_agent = locate(/datum/gas/sleeping_agent) in trace_gases - if(sleeping_agent && (sleeping_agent.moles > 1)) - graphic = 2 - else - graphic = 0 - - return graphic != graphic_archived - - proc/react(atom/dump_location) - //Purpose: Calculating if it is possible for a fire to occur in the airmix - //Called by: Air mixes updating? - //Inputs: None - //Outputs: If a fire occured - - var/reacting = 0 //set to 1 if a notable reaction occured (used by pipe_network) - - if(temperature > FIRE_MINIMUM_TEMPERATURE_TO_EXIST) - if(zburn(null) > 0) - reacting = 1 - - return reacting - - proc/fire() - //Purpose: Calculating any fire reactions. - //Called by: react() (See above) - //Inputs: None - //Outputs: How much fuel burned - - return zburn(null) - - /*var/energy_released = 0 - var/old_heat_capacity = heat_capacity() - - var/datum/gas/volatile_fuel/fuel_store = locate(/datum/gas/volatile_fuel) in trace_gases - if(fuel_store) //General volatile gas burn - var/burned_fuel = 0 - - if(oxygen < fuel_store.moles) - burned_fuel = oxygen - fuel_store.moles -= burned_fuel - oxygen = 0 - else - burned_fuel = fuel_store.moles - oxygen -= fuel_store.moles - del(fuel_store) - - energy_released += FIRE_CARBON_ENERGY_RELEASED * burned_fuel - carbon_dioxide += burned_fuel - fuel_burnt += burned_fuel - - //Handle plasma burning - if(toxins > MINIMUM_HEAT_CAPACITY) - var/plasma_burn_rate = 0 - var/oxygen_burn_rate = 0 - //more plasma released at higher temperatures - var/temperature_scale - if(temperature > PLASMA_UPPER_TEMPERATURE) - temperature_scale = 1 - else - temperature_scale = (temperature-PLASMA_MINIMUM_BURN_TEMPERATURE)/(PLASMA_UPPER_TEMPERATURE-PLASMA_MINIMUM_BURN_TEMPERATURE) - if(temperature_scale > 0) - oxygen_burn_rate = 1.4 - temperature_scale - if(oxygen > toxins*PLASMA_OXYGEN_FULLBURN) - plasma_burn_rate = (toxins*temperature_scale)/4 - else - plasma_burn_rate = (temperature_scale*(oxygen/PLASMA_OXYGEN_FULLBURN))/4 - if(plasma_burn_rate > MINIMUM_HEAT_CAPACITY) - toxins -= plasma_burn_rate - oxygen -= plasma_burn_rate*oxygen_burn_rate - carbon_dioxide += plasma_burn_rate - - energy_released += FIRE_PLASMA_ENERGY_RELEASED * (plasma_burn_rate) - - fuel_burnt += (plasma_burn_rate)*(1+oxygen_burn_rate) - - if(energy_released > 0) - var/new_heat_capacity = heat_capacity() - if(new_heat_capacity > MINIMUM_HEAT_CAPACITY) - temperature = (temperature*old_heat_capacity + energy_released)/new_heat_capacity - update_values() - - return fuel_burnt*/ - -////////////////////////////////////////////// -//Procs for general gas spread calculations.// -////////////////////////////////////////////// - - - proc/archive() - //Purpose: Archives the current gas values - //Called by: UNKNOWN - //Inputs: None - //Outputs: 1 - - oxygen_archived = oxygen - carbon_dioxide_archived = carbon_dioxide - nitrogen_archived = nitrogen - toxins_archived = toxins - - if(trace_gases.len) - for(var/datum/gas/trace_gas in trace_gases) - trace_gas.moles_archived = trace_gas.moles - - temperature_archived = temperature - - graphic_archived = graphic - - return 1 - - proc/check_then_merge(datum/gas_mixture/giver) - //Purpose: Similar to merge(...) but first checks to see if the amount of air assumed is small enough - // that group processing is still accurate for source (aborts if not) - //Called by: airgroups/machinery expelling air, ? - //Inputs: The gas to try and merge - //Outputs: 1 on successful merge. 0 otherwise. - - if(!giver) - return 0 - if(((giver.oxygen > MINIMUM_AIR_TO_SUSPEND) && (giver.oxygen >= oxygen*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ - || ((giver.carbon_dioxide > MINIMUM_AIR_TO_SUSPEND) && (giver.carbon_dioxide >= carbon_dioxide*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ - || ((giver.nitrogen > MINIMUM_AIR_TO_SUSPEND) && (giver.nitrogen >= nitrogen*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ - || ((giver.toxins > MINIMUM_AIR_TO_SUSPEND) && (giver.toxins >= toxins*MINIMUM_AIR_RATIO_TO_SUSPEND))) - return 0 - if(abs(giver.temperature - temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) - return 0 - - if(giver.trace_gases.len) - for(var/datum/gas/trace_gas in giver.trace_gases) - var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases - if((trace_gas.moles > MINIMUM_AIR_TO_SUSPEND) && (!corresponding || (trace_gas.moles >= corresponding.moles*MINIMUM_AIR_RATIO_TO_SUSPEND))) - return 0 - - return merge(giver) - - proc/merge(datum/gas_mixture/giver) - //Purpose: Merges all air from giver into self. Deletes giver. - //Called by: Machinery expelling air, check_then_merge, ? - //Inputs: The gas to merge. - //Outputs: 1 - - if(!giver) - return 0 - - if(abs(temperature-giver.temperature)>MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) - var/self_heat_capacity = heat_capacity()*group_multiplier - var/giver_heat_capacity = giver.heat_capacity()*giver.group_multiplier - var/combined_heat_capacity = giver_heat_capacity + self_heat_capacity - if(combined_heat_capacity != 0) - temperature = (giver.temperature*giver_heat_capacity + temperature*self_heat_capacity)/combined_heat_capacity - - if((group_multiplier>1)||(giver.group_multiplier>1)) - oxygen += giver.oxygen*giver.group_multiplier/group_multiplier - carbon_dioxide += giver.carbon_dioxide*giver.group_multiplier/group_multiplier - nitrogen += giver.nitrogen*giver.group_multiplier/group_multiplier - toxins += giver.toxins*giver.group_multiplier/group_multiplier - else - oxygen += giver.oxygen - carbon_dioxide += giver.carbon_dioxide - nitrogen += giver.nitrogen - toxins += giver.toxins - - if(giver.trace_gases.len) - for(var/datum/gas/trace_gas in giver.trace_gases) - var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases - if(!corresponding) - corresponding = new trace_gas.type() - trace_gases += corresponding - corresponding.moles += trace_gas.moles*giver.group_multiplier/group_multiplier - update_values() - - // Let the garbage collector handle it, faster according to /tg/ testers - //del(giver) - return 1 - - proc/remove(amount) - //Purpose: Removes a certain number of moles from the air. - //Called by: ? - //Inputs: How many moles to remove. - //Outputs: Removed air. - - var/sum = total_moles() - amount = min(amount,sum) //Can not take more air than tile has! - if(amount <= 0) - return null - - var/datum/gas_mixture/removed = new - - - removed.oxygen = QUANTIZE((oxygen/sum)*amount) - removed.nitrogen = QUANTIZE((nitrogen/sum)*amount) - removed.carbon_dioxide = QUANTIZE((carbon_dioxide/sum)*amount) - removed.toxins = QUANTIZE((toxins/sum)*amount) - - oxygen -= removed.oxygen/group_multiplier - nitrogen -= removed.nitrogen/group_multiplier - carbon_dioxide -= removed.carbon_dioxide/group_multiplier - toxins -= removed.toxins/group_multiplier - - if(trace_gases.len) - for(var/datum/gas/trace_gas in trace_gases) - var/datum/gas/corresponding = new trace_gas.type() - removed.trace_gases += corresponding - - corresponding.moles = (trace_gas.moles/sum)*amount - trace_gas.moles -= corresponding.moles/group_multiplier - - removed.temperature = temperature - update_values() - removed.update_values() - - return removed - - proc/remove_ratio(ratio) - //Purpose: Removes a certain ratio of the air. - //Called by: ? - //Inputs: Percentage to remove. - //Outputs: Removed air. - - if(ratio <= 0) - return null - - ratio = min(ratio, 1) - - var/datum/gas_mixture/removed = new - - removed.oxygen = QUANTIZE(oxygen*ratio) - removed.nitrogen = QUANTIZE(nitrogen*ratio) - removed.carbon_dioxide = QUANTIZE(carbon_dioxide*ratio) - removed.toxins = QUANTIZE(toxins*ratio) - - oxygen -= removed.oxygen/group_multiplier - nitrogen -= removed.nitrogen/group_multiplier - carbon_dioxide -= removed.carbon_dioxide/group_multiplier - toxins -= removed.toxins/group_multiplier - - if(trace_gases.len) - for(var/datum/gas/trace_gas in trace_gases) - var/datum/gas/corresponding = new trace_gas.type() - removed.trace_gases += corresponding - - corresponding.moles = trace_gas.moles*ratio - trace_gas.moles -= corresponding.moles/group_multiplier - - removed.temperature = temperature - update_values() - removed.update_values() - - return removed - - proc/check_then_remove(amount) - //Purpose: Similar to remove(...) but first checks to see if the amount of air removed is small enough - // that group processing is still accurate for source (aborts if not) - //Called by: ? - //Inputs: Number of moles to remove - //Outputs: Removed air or 0 if it can remove air or not. - - amount = min(amount,total_moles()) //Can not take more air than tile has! - - if((amount > MINIMUM_AIR_RATIO_TO_SUSPEND) && (amount > total_moles()*MINIMUM_AIR_RATIO_TO_SUSPEND)) - return 0 - - return remove(amount) - - proc/copy_from(datum/gas_mixture/sample) - //Purpose: Duplicates the sample air mixture. - //Called by: airgroups splitting, ? - //Inputs: Gas to copy - //Outputs: 1 - - oxygen = sample.oxygen - carbon_dioxide = sample.carbon_dioxide - nitrogen = sample.nitrogen - toxins = sample.toxins - total_moles = sample.total_moles() - - trace_gases.len=null - if(sample.trace_gases.len > 0) - for(var/datum/gas/trace_gas in sample.trace_gases) - var/datum/gas/corresponding = new trace_gas.type() - trace_gases += corresponding - - corresponding.moles = trace_gas.moles - - temperature = sample.temperature - - return 1 - - proc/check_gas_mixture(datum/gas_mixture/sharer) - //Purpose: Telling if one or both airgroups needs to disable group processing. - //Called by: Airgroups sharing air, checking if group processing needs disabled. - //Inputs: Gas to compare from other airgroup - //Outputs: 0 if the self-check failed (local airgroup breaks?) - // then -1 if sharer-check failed (sharing airgroup breaks?) - // then 1 if both checks pass (share succesful?) - if(!istype(sharer)) - return - - var/delta_oxygen = QUANTIZE(oxygen_archived - sharer.oxygen_archived)/TRANSFER_FRACTION - var/delta_carbon_dioxide = QUANTIZE(carbon_dioxide_archived - sharer.carbon_dioxide_archived)/TRANSFER_FRACTION - var/delta_nitrogen = QUANTIZE(nitrogen_archived - sharer.nitrogen_archived)/TRANSFER_FRACTION - var/delta_toxins = QUANTIZE(toxins_archived - sharer.toxins_archived)/TRANSFER_FRACTION - - var/delta_temperature = (temperature_archived - sharer.temperature_archived) - - if(((abs(delta_oxygen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_oxygen) >= oxygen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ - || ((abs(delta_carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_carbon_dioxide) >= carbon_dioxide_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ - || ((abs(delta_nitrogen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_nitrogen) >= nitrogen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ - || ((abs(delta_toxins) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_toxins) >= toxins_archived*MINIMUM_AIR_RATIO_TO_SUSPEND))) - return 0 - - if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) - return 0 - - if(sharer.trace_gases.len) - for(var/datum/gas/trace_gas in sharer.trace_gases) - if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND*4) - var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases - if(corresponding) - if(trace_gas.moles_archived >= corresponding.moles_archived*MINIMUM_AIR_RATIO_TO_SUSPEND*4) - return 0 - else - return 0 - - if(trace_gases.len) - for(var/datum/gas/trace_gas in trace_gases) - if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND*4) - if(!locate(trace_gas.type) in sharer.trace_gases) - return 0 - - if(((abs(delta_oxygen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_oxygen) >= sharer.oxygen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ - || ((abs(delta_carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_carbon_dioxide) >= sharer.carbon_dioxide_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ - || ((abs(delta_nitrogen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_nitrogen) >= sharer.nitrogen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ - || ((abs(delta_toxins) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_toxins) >= sharer.toxins_archived*MINIMUM_AIR_RATIO_TO_SUSPEND))) - return -1 - - if(trace_gases.len) - for(var/datum/gas/trace_gas in trace_gases) - if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND*4) - var/datum/gas/corresponding = locate(trace_gas.type) in sharer.trace_gases - if(corresponding) - if(trace_gas.moles_archived >= corresponding.moles_archived*MINIMUM_AIR_RATIO_TO_SUSPEND*4) - return -1 - else - return -1 - - return 1 - - proc/check_turf(turf/model) - //Purpose: Used to compare the gases in an unsimulated turf with the gas in a simulated one. - //Called by: Sharing air (mimicing) with adjacent unsimulated turfs - //Inputs: Unsimulated turf - //Outputs: 1 if safe to mimic, 0 if needs to break airgroup. - - var/delta_oxygen = (oxygen_archived - model.oxygen)/TRANSFER_FRACTION - var/delta_carbon_dioxide = (carbon_dioxide_archived - model.carbon_dioxide)/TRANSFER_FRACTION - var/delta_nitrogen = (nitrogen_archived - model.nitrogen)/TRANSFER_FRACTION - var/delta_toxins = (toxins_archived - model.toxins)/TRANSFER_FRACTION - - var/delta_temperature = (temperature_archived - model.temperature) - - if(((abs(delta_oxygen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_oxygen) >= oxygen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ - || ((abs(delta_carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_carbon_dioxide) >= carbon_dioxide_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ - || ((abs(delta_nitrogen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_nitrogen) >= nitrogen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ - || ((abs(delta_toxins) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_toxins) >= toxins_archived*MINIMUM_AIR_RATIO_TO_SUSPEND))) - return 0 - if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) - return 0 - - if(trace_gases.len) - for(var/datum/gas/trace_gas in trace_gases) - if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND*4) - return 0 - - return 1 - - proc/share(datum/gas_mixture/sharer) - //Purpose: Used to transfer gas from a more pressurised tile to a less presurised tile - // (Two directional, if the other tile is more pressurised, air travels to current tile) - //Called by: Sharing air with adjacent simulated turfs - //Inputs: Air datum to share with - //Outputs: Amount of gas exchanged (Negative if lost air, positive if gained.) - - - if(!istype(sharer)) - return - - var/delta_oxygen = QUANTIZE(oxygen_archived - sharer.oxygen_archived)/TRANSFER_FRACTION - var/delta_carbon_dioxide = QUANTIZE(carbon_dioxide_archived - sharer.carbon_dioxide_archived)/TRANSFER_FRACTION - var/delta_nitrogen = QUANTIZE(nitrogen_archived - sharer.nitrogen_archived)/TRANSFER_FRACTION - var/delta_toxins = QUANTIZE(toxins_archived - sharer.toxins_archived)/TRANSFER_FRACTION - - var/delta_temperature = (temperature_archived - sharer.temperature_archived) - - var/old_self_heat_capacity = 0 - var/old_sharer_heat_capacity = 0 - - var/heat_self_to_sharer = 0 - var/heat_capacity_self_to_sharer = 0 - var/heat_sharer_to_self = 0 - var/heat_capacity_sharer_to_self = 0 - - if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) - - var/delta_air = delta_oxygen+delta_nitrogen - if(delta_air) - var/air_heat_capacity = SPECIFIC_HEAT_AIR*delta_air - if(delta_air > 0) - heat_self_to_sharer += air_heat_capacity*temperature_archived - heat_capacity_self_to_sharer += air_heat_capacity - else - heat_sharer_to_self -= air_heat_capacity*sharer.temperature_archived - heat_capacity_sharer_to_self -= air_heat_capacity - - if(delta_carbon_dioxide) - var/carbon_dioxide_heat_capacity = SPECIFIC_HEAT_CDO*delta_carbon_dioxide - if(delta_carbon_dioxide > 0) - heat_self_to_sharer += carbon_dioxide_heat_capacity*temperature_archived - heat_capacity_self_to_sharer += carbon_dioxide_heat_capacity - else - heat_sharer_to_self -= carbon_dioxide_heat_capacity*sharer.temperature_archived - heat_capacity_sharer_to_self -= carbon_dioxide_heat_capacity - - if(delta_toxins) - var/toxins_heat_capacity = SPECIFIC_HEAT_TOXIN*delta_toxins - if(delta_toxins > 0) - heat_self_to_sharer += toxins_heat_capacity*temperature_archived - heat_capacity_self_to_sharer += toxins_heat_capacity - else - heat_sharer_to_self -= toxins_heat_capacity*sharer.temperature_archived - heat_capacity_sharer_to_self -= toxins_heat_capacity - - old_self_heat_capacity = heat_capacity()*group_multiplier - old_sharer_heat_capacity = sharer.heat_capacity()*sharer.group_multiplier - - oxygen -= delta_oxygen/group_multiplier - sharer.oxygen += delta_oxygen/sharer.group_multiplier - - carbon_dioxide -= delta_carbon_dioxide/group_multiplier - sharer.carbon_dioxide += delta_carbon_dioxide/sharer.group_multiplier - - nitrogen -= delta_nitrogen/group_multiplier - sharer.nitrogen += delta_nitrogen/sharer.group_multiplier - - toxins -= delta_toxins/group_multiplier - sharer.toxins += delta_toxins/sharer.group_multiplier - - var/moved_moles = (delta_oxygen + delta_carbon_dioxide + delta_nitrogen + delta_toxins) - - var/list/trace_types_considered = list() - - if(trace_gases.len) - for(var/datum/gas/trace_gas in trace_gases) - - var/datum/gas/corresponding = locate(trace_gas.type) in sharer.trace_gases - var/delta = 0 - - if(corresponding) - delta = QUANTIZE(trace_gas.moles_archived - corresponding.moles_archived)/TRANSFER_FRACTION - else - corresponding = new trace_gas.type() - sharer.trace_gases += corresponding - - delta = trace_gas.moles_archived/TRANSFER_FRACTION - - trace_gas.moles -= delta/group_multiplier - corresponding.moles += delta/sharer.group_multiplier - - if(delta) - var/individual_heat_capacity = trace_gas.specific_heat*delta - if(delta > 0) - heat_self_to_sharer += individual_heat_capacity*temperature_archived - heat_capacity_self_to_sharer += individual_heat_capacity - else - heat_sharer_to_self -= individual_heat_capacity*sharer.temperature_archived - heat_capacity_sharer_to_self -= individual_heat_capacity - - moved_moles += delta - - trace_types_considered += trace_gas.type - - - if(sharer.trace_gases.len) - for(var/datum/gas/trace_gas in sharer.trace_gases) - if(trace_gas.type in trace_types_considered) continue - else - var/datum/gas/corresponding - var/delta = 0 - - corresponding = new trace_gas.type() - trace_gases += corresponding - - delta = trace_gas.moles_archived/TRANSFER_FRACTION - - trace_gas.moles -= delta/sharer.group_multiplier - corresponding.moles += delta/group_multiplier - - //Guaranteed transfer from sharer to self - var/individual_heat_capacity = trace_gas.specific_heat*delta - heat_sharer_to_self += individual_heat_capacity*sharer.temperature_archived - heat_capacity_sharer_to_self += individual_heat_capacity - - moved_moles += -delta - update_values() - sharer.update_values() - - if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) - var/new_self_heat_capacity = old_self_heat_capacity + heat_capacity_sharer_to_self - heat_capacity_self_to_sharer - var/new_sharer_heat_capacity = old_sharer_heat_capacity + heat_capacity_self_to_sharer - heat_capacity_sharer_to_self - - if(new_self_heat_capacity > MINIMUM_HEAT_CAPACITY) - temperature = (old_self_heat_capacity*temperature - heat_capacity_self_to_sharer*temperature_archived + heat_capacity_sharer_to_self*sharer.temperature_archived)/new_self_heat_capacity - - if(new_sharer_heat_capacity > MINIMUM_HEAT_CAPACITY) - sharer.temperature = (old_sharer_heat_capacity*sharer.temperature-heat_capacity_sharer_to_self*sharer.temperature_archived + heat_capacity_self_to_sharer*temperature_archived)/new_sharer_heat_capacity - - if(abs(old_sharer_heat_capacity) > MINIMUM_HEAT_CAPACITY) - if(abs(new_sharer_heat_capacity/old_sharer_heat_capacity - 1) < 0.10) // <10% change in sharer heat capacity - temperature_share(sharer, OPEN_HEAT_TRANSFER_COEFFICIENT) - - if((delta_temperature > MINIMUM_TEMPERATURE_TO_MOVE) || abs(moved_moles) > MINIMUM_MOLES_DELTA_TO_MOVE) - var/delta_pressure = temperature_archived*(total_moles() + moved_moles) - sharer.temperature_archived*(sharer.total_moles() - moved_moles) - return delta_pressure*R_IDEAL_GAS_EQUATION/volume - - else - return 0 - - proc/mimic(turf/model, border_multiplier) - //Purpose: Used transfer gas from a more pressurised tile to a less presurised unsimulated tile. - //Called by: "sharing" from unsimulated to simulated turfs. - //Inputs: Unsimulated turf, Multiplier for gas transfer (optional) - //Outputs: Amount of gas exchanged - - var/delta_oxygen = QUANTIZE(oxygen_archived - model.oxygen)/TRANSFER_FRACTION - var/delta_carbon_dioxide = QUANTIZE(carbon_dioxide_archived - model.carbon_dioxide)/TRANSFER_FRACTION - var/delta_nitrogen = QUANTIZE(nitrogen_archived - model.nitrogen)/TRANSFER_FRACTION - var/delta_toxins = QUANTIZE(toxins_archived - model.toxins)/TRANSFER_FRACTION - - var/delta_temperature = (temperature_archived - model.temperature) - - var/heat_transferred = 0 - var/old_self_heat_capacity = 0 - var/heat_capacity_transferred = 0 - - if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) - - var/delta_air = delta_oxygen+delta_nitrogen - if(delta_air) - var/air_heat_capacity = SPECIFIC_HEAT_AIR*delta_air - heat_transferred -= air_heat_capacity*model.temperature - heat_capacity_transferred -= air_heat_capacity - - if(delta_carbon_dioxide) - var/carbon_dioxide_heat_capacity = SPECIFIC_HEAT_CDO*delta_carbon_dioxide - heat_transferred -= carbon_dioxide_heat_capacity*model.temperature - heat_capacity_transferred -= carbon_dioxide_heat_capacity - - if(delta_toxins) - var/toxins_heat_capacity = SPECIFIC_HEAT_TOXIN*delta_toxins - heat_transferred -= toxins_heat_capacity*model.temperature - heat_capacity_transferred -= toxins_heat_capacity - - old_self_heat_capacity = heat_capacity()*group_multiplier - - if(border_multiplier) - oxygen -= delta_oxygen*border_multiplier/group_multiplier - carbon_dioxide -= delta_carbon_dioxide*border_multiplier/group_multiplier - nitrogen -= delta_nitrogen*border_multiplier/group_multiplier - toxins -= delta_toxins*border_multiplier/group_multiplier - else - oxygen -= delta_oxygen/group_multiplier - carbon_dioxide -= delta_carbon_dioxide/group_multiplier - nitrogen -= delta_nitrogen/group_multiplier - toxins -= delta_toxins/group_multiplier - - var/moved_moles = (delta_oxygen + delta_carbon_dioxide + delta_nitrogen + delta_toxins) - - if(trace_gases.len) - for(var/datum/gas/trace_gas in trace_gases) - var/delta = 0 - - delta = trace_gas.moles_archived/TRANSFER_FRACTION - - if(border_multiplier) - trace_gas.moles -= delta*border_multiplier/group_multiplier - else - trace_gas.moles -= delta/group_multiplier - - var/heat_cap_transferred = delta*trace_gas.specific_heat - heat_transferred += heat_cap_transferred*temperature_archived - heat_capacity_transferred += heat_cap_transferred - moved_moles += delta - update_values() - - if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) - var/new_self_heat_capacity = old_self_heat_capacity - heat_capacity_transferred - if(new_self_heat_capacity > MINIMUM_HEAT_CAPACITY) - if(border_multiplier) - temperature = (old_self_heat_capacity*temperature - heat_capacity_transferred*border_multiplier*temperature_archived)/new_self_heat_capacity - else - temperature = (old_self_heat_capacity*temperature - heat_capacity_transferred*border_multiplier*temperature_archived)/new_self_heat_capacity - - temperature_mimic(model, model.thermal_conductivity, border_multiplier) - - if((delta_temperature > MINIMUM_TEMPERATURE_TO_MOVE) || abs(moved_moles) > MINIMUM_MOLES_DELTA_TO_MOVE) - var/delta_pressure = temperature_archived*(total_moles() + moved_moles) - model.temperature*(model.oxygen+model.carbon_dioxide+model.nitrogen+model.toxins) - return delta_pressure*R_IDEAL_GAS_EQUATION/volume - else - return 0 - - proc/check_both_then_temperature_share(datum/gas_mixture/sharer, conduction_coefficient) - var/delta_temperature = (temperature_archived - sharer.temperature_archived) - - var/self_heat_capacity = heat_capacity_archived() - var/sharer_heat_capacity = sharer.heat_capacity_archived() - - var/self_temperature_delta = 0 - var/sharer_temperature_delta = 0 - - if((sharer_heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY)) - var/heat = conduction_coefficient*delta_temperature* \ - (self_heat_capacity*sharer_heat_capacity/(self_heat_capacity+sharer_heat_capacity)) - - self_temperature_delta = -heat/(self_heat_capacity*group_multiplier) - sharer_temperature_delta = heat/(sharer_heat_capacity*sharer.group_multiplier) - else - return 1 - - if((abs(self_temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) \ - && (abs(self_temperature_delta) > MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND*temperature_archived)) - return 0 - - if((abs(sharer_temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) \ - && (abs(sharer_temperature_delta) > MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND*sharer.temperature_archived)) - return -1 - - temperature += self_temperature_delta - sharer.temperature += sharer_temperature_delta - - return 1 - //Logic integrated from: temperature_share(sharer, conduction_coefficient) for efficiency - - proc/check_me_then_temperature_share(datum/gas_mixture/sharer, conduction_coefficient) - var/delta_temperature = (temperature_archived - sharer.temperature_archived) - - var/self_heat_capacity = heat_capacity_archived() - var/sharer_heat_capacity = sharer.heat_capacity_archived() - - var/self_temperature_delta = 0 - var/sharer_temperature_delta = 0 - - if((sharer_heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY)) - var/heat = conduction_coefficient*delta_temperature* \ - (self_heat_capacity*sharer_heat_capacity/(self_heat_capacity+sharer_heat_capacity)) - - self_temperature_delta = -heat/(self_heat_capacity*group_multiplier) - sharer_temperature_delta = heat/(sharer_heat_capacity*sharer.group_multiplier) - else - return 1 - - if((abs(self_temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) \ - && (abs(self_temperature_delta) > MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND*temperature_archived)) - return 0 - - temperature += self_temperature_delta - sharer.temperature += sharer_temperature_delta - - return 1 - //Logic integrated from: temperature_share(sharer, conduction_coefficient) for efficiency - - proc/check_me_then_temperature_turf_share(turf/simulated/sharer, conduction_coefficient) - var/delta_temperature = (temperature_archived - sharer.temperature) - - var/self_temperature_delta = 0 - var/sharer_temperature_delta = 0 - - if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) - var/self_heat_capacity = heat_capacity_archived() - - if((sharer.heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY)) - var/heat = conduction_coefficient*delta_temperature* \ - (self_heat_capacity*sharer.heat_capacity/(self_heat_capacity+sharer.heat_capacity)) - - self_temperature_delta = -heat/(self_heat_capacity*group_multiplier) - sharer_temperature_delta = heat/sharer.heat_capacity - else - return 1 - - if((abs(self_temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) \ - && (abs(self_temperature_delta) > MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND*temperature_archived)) - return 0 - - temperature += self_temperature_delta - sharer.temperature += sharer_temperature_delta - - return 1 - //Logic integrated from: temperature_turf_share(sharer, conduction_coefficient) for efficiency - - proc/check_me_then_temperature_mimic(turf/model, conduction_coefficient) - var/delta_temperature = (temperature_archived - model.temperature) - var/self_temperature_delta = 0 - - if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) - var/self_heat_capacity = heat_capacity_archived() - - if((model.heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY)) - var/heat = conduction_coefficient*delta_temperature* \ - (self_heat_capacity*model.heat_capacity/(self_heat_capacity+model.heat_capacity)) - - self_temperature_delta = -heat/(self_heat_capacity*group_multiplier) - - if((abs(self_temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) \ - && (abs(self_temperature_delta) > MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND*temperature_archived)) - return 0 - - temperature += self_temperature_delta - - return 1 - //Logic integrated from: temperature_mimic(model, conduction_coefficient) for efficiency - - proc/temperature_share(datum/gas_mixture/sharer, conduction_coefficient) - - var/delta_temperature = (temperature_archived - sharer.temperature_archived) - if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) - var/self_heat_capacity = heat_capacity_archived() - var/sharer_heat_capacity = sharer.heat_capacity_archived() - if(!group_multiplier) - message_admins("Error! The gas mixture (ref \ref[src]) has no group multiplier!") - return - - if((sharer_heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY)) - var/heat = conduction_coefficient*delta_temperature* \ - (self_heat_capacity*sharer_heat_capacity/(self_heat_capacity+sharer_heat_capacity)) - - temperature -= heat/(self_heat_capacity*group_multiplier) - sharer.temperature += heat/(sharer_heat_capacity*sharer.group_multiplier) - - proc/temperature_mimic(turf/model, conduction_coefficient, border_multiplier) - var/delta_temperature = (temperature - model.temperature) - if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) - var/self_heat_capacity = heat_capacity()//_archived() - if(!group_multiplier) - message_admins("Error! The gas mixture (ref \ref[src]) has no group multiplier!") - return - - if((model.heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY)) - var/heat = conduction_coefficient*delta_temperature* \ - (self_heat_capacity*model.heat_capacity/(self_heat_capacity+model.heat_capacity)) - - if(border_multiplier) - temperature -= heat*border_multiplier/(self_heat_capacity*group_multiplier) - else - temperature -= heat/(self_heat_capacity*group_multiplier) - - proc/temperature_turf_share(turf/simulated/sharer, conduction_coefficient) - var/delta_temperature = (temperature_archived - sharer.temperature) - if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) - var/self_heat_capacity = heat_capacity() - - if((sharer.heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY)) - var/heat = conduction_coefficient*delta_temperature* \ - (self_heat_capacity*sharer.heat_capacity/(self_heat_capacity+sharer.heat_capacity)) - - temperature -= heat/(self_heat_capacity*group_multiplier) - sharer.temperature += heat/sharer.heat_capacity - - proc/compare(datum/gas_mixture/sample) - //Purpose: Compares sample to self to see if within acceptable ranges that group processing may be enabled - //Called by: Airgroups trying to rebuild - //Inputs: Gas mix to compare - //Outputs: 1 if can rebuild, 0 if not. - if(!sample) return 0 - - if((abs(oxygen-sample.oxygen) > MINIMUM_AIR_TO_SUSPEND) && \ - ((oxygen < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.oxygen) || (oxygen > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.oxygen))) - return 0 - if((abs(nitrogen-sample.nitrogen) > MINIMUM_AIR_TO_SUSPEND) && \ - ((nitrogen < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.nitrogen) || (nitrogen > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.nitrogen))) - return 0 - if((abs(carbon_dioxide-sample.carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && \ - ((carbon_dioxide < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.carbon_dioxide) || (oxygen > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.carbon_dioxide))) - return 0 - if((abs(toxins-sample.toxins) > MINIMUM_AIR_TO_SUSPEND) && \ - ((toxins < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.toxins) || (toxins > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.toxins))) - return 0 - - if(total_moles() > MINIMUM_AIR_TO_SUSPEND) - if((abs(temperature-sample.temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) && \ - ((temperature < (1-MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND)*sample.temperature) || (temperature > (1+MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND)*sample.temperature))) - //world << "temp fail [temperature] & [sample.temperature]" - return 0 - - if(sample.trace_gases.len) - for(var/datum/gas/trace_gas in sample.trace_gases) - if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND) - var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases - if(corresponding) - if((abs(trace_gas.moles - corresponding.moles) > MINIMUM_AIR_TO_SUSPEND) && \ - ((corresponding.moles < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*trace_gas.moles) || (corresponding.moles > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*trace_gas.moles))) - return 0 - else - return 0 - - if(trace_gases.len) - for(var/datum/gas/trace_gas in trace_gases) - if(trace_gas.moles > MINIMUM_AIR_TO_SUSPEND) - var/datum/gas/corresponding = locate(trace_gas.type) in sample.trace_gases - if(corresponding) - if((abs(trace_gas.moles - corresponding.moles) > MINIMUM_AIR_TO_SUSPEND) && \ - ((trace_gas.moles < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*corresponding.moles) || (trace_gas.moles > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*corresponding.moles))) - return 0 - else - return 0 - return 1 - - - proc/subtract(datum/gas_mixture/right_side) - //Purpose: Subtracts right_side from air_mixture. Used to help turfs mingle - //Called by: Pipelines ending in a break (or something) - //Inputs: Gas mix to remove - //Outputs: 1 - - oxygen -= right_side.oxygen - carbon_dioxide -= right_side.carbon_dioxide - nitrogen -= right_side.nitrogen - toxins -= right_side.toxins - - if((trace_gases.len > 0)||(right_side.trace_gases.len > 0)) - for(var/datum/gas/trace_gas in right_side.trace_gases) - var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases - if(!corresponding) - corresponding = new trace_gas.type() - trace_gases += corresponding - - corresponding.moles -= trace_gas.moles - update_values() - return 1 \ No newline at end of file diff --git a/code/ZAS - vgstation/NewSettings.dm b/code/ZAS - vgstation/NewSettings.dm deleted file mode 100644 index a65fd6c8bec..00000000000 --- a/code/ZAS - vgstation/NewSettings.dm +++ /dev/null @@ -1,500 +0,0 @@ -/* -ZAS Settings System 2.0 - -Okay, so VariableSettings is a mess of spaghetticode and - is about as flexible as a grandmother covered in - starch. - -This is an attempt to fix that by using getters and - setters instead of stupidity. It's a little more difficult - to code with, but dammit, it's better than hackery. - -NOTE: plc was merged into the main settings. We can set up - visual groups later. - -HOW2GET: - zas_setting.Get(/datum/ZAS_Setting/herp) - -HOW2SET: - zas_setting.Set(/datum/ZAS_Setting/herp, "dsfargeg") -*/ - -var/global/ZAS_Settings/zas_settings = new - -#define ZAS_TYPE_UNDEFINED -1 -#define ZAS_TYPE_BOOLEAN 0 -#define ZAS_TYPE_NUMERIC 1 - -/** -* ZAS Setting Datum -* -* Stores a single setting. -* @author N3X15 -* @package SS13 -* @subpackage ZAS -*/ -/datum/ZAS_Setting/ - var/name="Clown" // Friendly name. - var/desc="Honk" - var/value=null - var/valtype=ZAS_TYPE_UNDEFINED - -/datum/ZAS_Setting/fire_consumption_rate - name = "Fire - Air Consumption Ratio" - desc = "Ratio of air removed and combusted per tick." - valtype=ZAS_TYPE_NUMERIC - value = 0.75 - -/datum/ZAS_Setting/fire_firelevel_multiplier - value = 25 - name = "Fire - Firelevel Constant" - desc = "Multiplied by the equation for firelevel, affects mainly the extingiushing of fires." - valtype=ZAS_TYPE_NUMERIC - -/datum/ZAS_Setting/fire_fuel_energy_release - value = 550000 - name = "Fire - Fuel energy release" - desc = "The energy in joule released when burning one mol of a burnable substance" - valtype=ZAS_TYPE_NUMERIC - -/datum/ZAS_Setting/airflow_lightest_pressure - value = 20 - name = "Airflow - Small Movement Threshold %" - desc = "Percent of 1 Atm. at which items with the small weight classes will move." - valtype=ZAS_TYPE_NUMERIC - -/datum/ZAS_Setting/airflow_light_pressure - value = 35 - name = "Airflow - Medium Movement Threshold %" - desc = "Percent of 1 Atm. at which items with the medium weight classes will move." - valtype=ZAS_TYPE_NUMERIC - -/datum/ZAS_Setting/airflow_medium_pressure - value = 50 - name = "Airflow - Heavy Movement Threshold %" - desc = "Percent of 1 Atm. at which items with the largest weight classes will move." - valtype=ZAS_TYPE_NUMERIC - -/datum/ZAS_Setting/airflow_heavy_pressure - value = 65 - name = "Airflow - Mob Movement Threshold %" - desc = "Percent of 1 Atm. at which mobs will move." - valtype=ZAS_TYPE_NUMERIC - -/datum/ZAS_Setting/airflow_dense_pressure - value = 85 - name = "Airflow - Dense Movement Threshold %" - desc = "Percent of 1 Atm. at which items with canisters and closets will move." - valtype=ZAS_TYPE_NUMERIC - -/datum/ZAS_Setting/airflow_stun_pressure - value = 60 - name = "Airflow - Mob Stunning Threshold %" - desc = "Percent of 1 Atm. at which mobs will be stunned by airflow." - valtype=ZAS_TYPE_NUMERIC - -/datum/ZAS_Setting/airflow_stun_cooldown - value = 60 - name = "Aiflow Stunning - Cooldown" - desc = "How long, in tenths of a second, to wait before stunning them again." - valtype=ZAS_TYPE_NUMERIC - -/datum/ZAS_Setting/airflow_stun - value = 1 - name = "Airflow Impact - Stunning" - desc = "How much a mob is stunned when hit by an object." - valtype=ZAS_TYPE_NUMERIC - -/datum/ZAS_Setting/airflow_damage - value = 2 - name = "Airflow Impact - Damage" - desc = "Damage from airflow impacts." - valtype=ZAS_TYPE_NUMERIC - -/datum/ZAS_Setting/airflow_speed_decay - value = 1.5 - name = "Airflow Speed Decay" - desc = "How rapidly the speed gained from airflow decays." - valtype=ZAS_TYPE_NUMERIC - -/datum/ZAS_Setting/airflow_delay - value = 30 - name = "Airflow Retrigger Delay" - desc = "Time in deciseconds before things can be moved by airflow again." - valtype=ZAS_TYPE_NUMERIC - -/datum/ZAS_Setting/airflow_mob_slowdown - value = 1 - name = "Airflow Slowdown" - desc = "Time in tenths of a second to add as a delay to each movement by a mob if they are fighting the pull of the airflow." - valtype=ZAS_TYPE_NUMERIC - -// N3X15 - Added back in so we can tweak performance. -/datum/ZAS_Setting/airflow_push - name="Airflow - Push" - value = 0 - desc="1=yes please rape my server, 0=no" - valtype=ZAS_TYPE_BOOLEAN - -/datum/ZAS_Setting/connection_insulation - value = 0.4 - name = "Connections - Insulation" - desc = "How insulative a connection is, in terms of heat transfer. 1 is perfectly insulative, and 0 is perfectly conductive." - valtype=ZAS_TYPE_NUMERIC - -/datum/ZAS_Setting/connection_temperature_delta - value = 10 - name = "Connections - Temperature Difference" - desc = "The smallest temperature difference which will cause heat to travel through doors." - valtype=ZAS_TYPE_NUMERIC - - -/////////////////////////////////////// -// PLASMA SHIT -/////////////////////////////////////// -// ALL CAPS BECAUSE PLASMA IS HARDCORE YO -// And I'm too lazy to fix the refs. - -/datum/ZAS_Setting/PLASMA_DMG - name = "Plasma Damage Amount" - desc = "Self Descriptive" - value = 3 - valtype=ZAS_TYPE_NUMERIC - -/datum/ZAS_Setting/CLOTH_CONTAMINATION - name = "Cloth Contamination" - desc = "If this is on, plasma does damage by getting into cloth." - value = 1 - valtype=ZAS_TYPE_BOOLEAN - -/datum/ZAS_Setting/PLASMAGUARD_ONLY - name = "PlasmaGuard Only" - desc = "If this is on, only biosuits and spacesuits protect against contamination and ill effects." - value = 0 - valtype=ZAS_TYPE_BOOLEAN - -/datum/ZAS_Setting/GENETIC_CORRUPTION - name = "Genetic Corruption Chance" - desc = "Chance of genetic corruption as well as toxic damage, X in 10,000." - value = 0 - valtype=ZAS_TYPE_BOOLEAN - -/datum/ZAS_Setting/SKIN_BURNS - name = "Skin Burns" - desc = "Plasma has an effect similar to mustard gas on the un-suited." - value = 0 - valtype=ZAS_TYPE_BOOLEAN - -/datum/ZAS_Setting/EYE_BURNS - name = "Eye Burns" - desc = "Plasma burns the eyes of anyone not wearing eye protection." - value = 1 - valtype=ZAS_TYPE_BOOLEAN - -/datum/ZAS_Setting/CONTAMINATION_LOSS - name = "Contamination Loss" - desc = "How much toxin damage is dealt from contaminated clothing" - value = 0.02 //Per tick? ASK ARYN - valtype=ZAS_TYPE_NUMERIC - -/datum/ZAS_Setting/PLASMA_HALLUCINATION - name = "Plasma Hallucination" - desc = "Does being in plasma cause you to hallucinate?" - value = 0 - valtype=ZAS_TYPE_BOOLEAN - -/datum/ZAS_Setting/N2O_HALLUCINATION - name = "N2O Hallucination" - desc = "Does being in sleeping gas cause you to hallucinate?" - value = 1 - valtype=ZAS_TYPE_BOOLEAN - -/** -* ZAS Settings -* -* Stores our settings for ZAS in an editable form. -* @author N3X15 -* @package SS13 -* @subpackage ZAS -*/ -/ZAS_Settings - // INTERNAL USE ONLY - var/list/datum/ZAS_Setting/settings = list() - -/ZAS_Settings/New() - .=..() - for(var/S in typesof(/datum/ZAS_Setting) - /datum/ZAS_Setting) - var/id=idfrompath("[S]") - //testing("Creating zas_settings\[[id]\] = new [S]") - src.settings[id]=new S - - - if(fexists("config/ZAS.txt") == 0) - Save() - Load() - -/ZAS_Settings/proc/Save() - var/F = file("config/ZAS.txt") - fdel(F) - for(var/id in src.settings) - var/datum/ZAS_Setting/setting = src.settings[id] - F << "# [setting.name]" - F << "# [setting.desc]" - F << "[id] [setting.value]" - F << "" - -/ZAS_Settings/proc/Load() - for(var/t in file2list("config/ZAS.txt")) - if(!t) continue - - t = trim(t) - if (length(t) == 0) - continue - else if (copytext(t, 1, 2) == "#") - continue - - var/pos = findtext(t, " ") - var/name = null - var/value = null - - if (pos) - name = copytext(t, 1, pos) - value = copytext(t, pos + 1) - else - name = t - - if (!name) - continue - - src.SetFromConfig(name,value) - -// INTERNAL USE ONLY -/ZAS_Settings/proc/idfrompath(var/str) - return replacetext(str,"/datum/ZAS_Setting/","") - -// INTERNAL USE ONLY -/ZAS_Settings/proc/ChangeSetting(var/user,var/id) - var/datum/ZAS_Setting/setting = src.settings[id] - var/displayedValue="" - switch(setting.valtype) - if(ZAS_TYPE_NUMERIC) - setting.value = input(user,"Enter a number:","Settings",setting.value) as num - displayedValue="\"[setting.value]\"" - /* - if(ZAS_TYPE_BITFLAG) - var/flag = input(user,"Toggle which bit?","Settings") in bitflags - flag = text2num(flag) - if(newvar & flag) - newvar &= ~flag - else - newvar |= flag - */ - if(ZAS_TYPE_BOOLEAN) - setting.value = !setting.value - displayedValue = (setting.value) ? "ON" : "OFF" - /* - if(ZAS_TYPE_STRING) - setting.value = input(user,"Enter text:","Settings",newvar) as message - */ - else - error("[id] has an invalid typeval.") - return - world << "\blue [key_name(user)] changed ZAS setting [setting.name] to [displayedValue]." - - ChangeSettingsDialog(user) - -/** -* Set the value of a setting. -* -* Recommended to use the actual type of the setting rather than the ID, since -* this will allow for the compiler to check the validity of id. Kinda. -* -* @param id Either the typepath of the desired setting, or the string ID of the setting. -* @param value The value that the setting should be set to. -*/ -/ZAS_Settings/proc/Set(var/id, var/value) - var/datum/ZAS_Setting/setting = src.settings[idfrompath(id)] - setting.value=value - -// INTERNAL USE ONLY -/ZAS_Settings/proc/SetFromConfig(var/id, var/value) - var/datum/ZAS_Setting/setting = src.settings[id] - switch(setting.valtype) - if(ZAS_TYPE_NUMERIC) - setting.value = text2num(value) - /* - if(ZAS_TYPE_BITFLAG) - var/flag = input(user,"Toggle which bit?","Settings") in bitflags - flag = text2num(flag) - if(newvar & flag) - newvar &= ~flag - else - newvar |= flag - */ - if(ZAS_TYPE_BOOLEAN) - setting.value = (value == "1") - /* - if(ZAS_TYPE_STRING) - setting.value = input(user,"Enter text:","Settings",newvar) as message - */ - -/** -* Get a setting. -* -* Recommended to use the actual type of the setting rather than the ID, since -* this will allow for the compiler to check the validity of id. Kinda. -* -* @param id Either the typepath of the desired setting, or the string ID of the setting. -* @returns Value of the desired setting -*/ -/ZAS_Settings/proc/Get(var/id) - if(ispath(id)) - id="[id]" - var/datum/ZAS_Setting/setting = src.settings[idfrompath(id)] - if(!setting || !istype(setting)) - world.log << "ZAS_SETTING DEBUG: [id] | [idfrompath(id)]" - return setting.value - -/ZAS_Settings/proc/ChangeSettingsDialog(mob/user) - var/dat = {" - - - ZAS Settings 2.0 - - - -

ZAS Configuration

-

Save Settings | Load Settings

-

Please note that changing these settings can and probably will result in death, destruction and mayhem. Change at your own risk.

-
"} - for(var/id in src.settings) - var/datum/ZAS_Setting/s = src.settings[id] - dat += "
[s.name] = [s.value] \[Change\]
" - dat += "
[s.desc]
" - dat += "
" - user << browse(dat,"window=settings") - -/ZAS_Settings/Topic(href,href_list) - if("changevar" in href_list) - ChangeSetting(usr,href_list["changevar"]) - if("save" in href_list) - var/sure = input(usr,"Are you sure? This will overwrite your ZAS configuration!","Overwrite ZAS.txt?", "No") in list("Yes","No") - if(sure=="Yes") - Save() - message_admins("[key_name(usr)] saved ZAS settings to disk.") - if("load" in href_list) - var/sure = input(usr,"Are you sure?","Reload ZAS.txt?", "No") in list("Yes","No") - if(sure=="Yes") - Load() - message_admins("[key_name(usr)] reloaded ZAS settings from disk.") - -/ZAS_Settings/proc/SetDefault(var/mob/user) - var/list/setting_choices = list("Plasma - Standard", "Plasma - Low Hazard", "Plasma - High Hazard", "Plasma - Oh Shit!", "ZAS - Normal", "ZAS - Forgiving", "ZAS - Dangerous", "ZAS - Hellish") - var/def = input(user, "Which of these presets should be used?") as null|anything in setting_choices - if(!def) - return - switch(def) - if("Plasma - Standard") - Set("CLOTH_CONTAMINATION", 1) //If this is on, plasma does damage by getting into cloth. - Set("PLASMAGUARD_ONLY", 0) - Set("GENETIC_CORRUPTION", 0) //Chance of genetic corruption as well as toxic damage, X in 1000. - Set("SKIN_BURNS", 0) //Plasma has an effect similar to mustard gas on the un-suited. - Set("EYE_BURNS", 1) //Plasma burns the eyes of anyone not wearing eye protection. - Set("PLASMA_HALLUCINATION", 0) - Set("CONTAMINATION_LOSS", 0.02) - - if("Plasma - Low Hazard") - Set("CLOTH_CONTAMINATION", 0) //If this is on, plasma does damage by getting into cloth. - Set("PLASMAGUARD_ONLY", 0) - Set("GENETIC_CORRUPTION", 0) //Chance of genetic corruption as well as toxic damage, X in 1000 - Set("SKIN_BURNS", 0) //Plasma has an effect similar to mustard gas on the un-suited. - Set("EYE_BURNS", 1) //Plasma burns the eyes of anyone not wearing eye protection. - Set("PLASMA_HALLUCINATION", 0) - Set("CONTAMINATION_LOSS", 0.01) - - if("Plasma - High Hazard") - Set("CLOTH_CONTAMINATION", 1) //If this is on, plasma does damage by getting into cloth. - Set("PLASMAGUARD_ONLY", 0) - Set("GENETIC_CORRUPTION", 0) //Chance of genetic corruption as well as toxic damage, X in 1000. - Set("SKIN_BURNS", 1) //Plasma has an effect similar to mustard gas on the un-suited. - Set("EYE_BURNS", 1) //Plasma burns the eyes of anyone not wearing eye protection. - Set("PLASMA_HALLUCINATION", 1) - Set("CONTAMINATION_LOSS", 0.05) - - if("Plasma - Oh Shit!") - Set("CLOTH_CONTAMINATION", 1) //If this is on, plasma does damage by getting into cloth. - Set("PLASMAGUARD_ONLY", 1) - Set("GENETIC_CORRUPTION", 5) //Chance of genetic corruption as well as toxic damage, X in 1000. - Set("SKIN_BURNS", 1) //Plasma has an effect similar to mustard gas on the un-suited. - Set("EYE_BURNS", 1) //Plasma burns the eyes of anyone not wearing eye protection. - Set("PLASMA_HALLUCINATION", 1) - Set("CONTAMINATION_LOSS", 0.075) - - if("ZAS - Normal") - Set("airflow_push", 0) - Set("airflow_lightest_pressure", 20) - Set("airflow_light_pressure", 35) - Set("airflow_medium_pressure", 50) - Set("airflow_heavy_pressure", 65) - Set("airflow_dense_pressure", 85) - Set("airflow_stun_pressure", 60) - Set("airflow_stun_cooldown", 60) - Set("airflow_stun", 1) - Set("airflow_damage", 2) - Set("airflow_speed_decay", 1.5) - Set("airflow_delay", 30) - Set("airflow_mob_slowdown", 1) - - if("ZAS - Forgiving") - Set("airflow_push", 0) - Set("airflow_lightest_pressure", 45) - Set("airflow_light_pressure", 60) - Set("airflow_medium_pressure", 120) - Set("airflow_heavy_pressure", 110) - Set("airflow_dense_pressure", 200) - Set("airflow_stun_pressure", 150) - Set("airflow_stun_cooldown", 90) - Set("airflow_stun", 0.15) - Set("airflow_damage", 0.15) - Set("airflow_speed_decay", 1.5) - Set("airflow_delay", 50) - Set("airflow_mob_slowdown", 0) - - if("ZAS - Dangerous") - Set("airflow_push", 1) - Set("airflow_lightest_pressure", 15) - Set("airflow_light_pressure", 30) - Set("airflow_medium_pressure", 45) - Set("airflow_heavy_pressure", 55) - Set("airflow_dense_pressure", 70) - Set("airflow_stun_pressure", 50) - Set("airflow_stun_cooldown", 50) - Set("airflow_stun", 2) - Set("airflow_damage", 3) - Set("airflow_speed_decay", 1.2) - Set("airflow_delay", 25) - Set("airflow_mob_slowdown", 2) - - if("ZAS - Hellish") - Set("airflow_push", 1) - Set("airflow_lightest_pressure", 20) - Set("airflow_light_pressure", 30) - Set("airflow_medium_pressure", 40) - Set("airflow_heavy_pressure", 50) - Set("airflow_dense_pressure", 60) - Set("airflow_stun_pressure", 40) - Set("airflow_stun_cooldown", 40) - Set("airflow_stun", 3) - Set("airflow_damage", 4) - Set("airflow_speed_decay", 1) - Set("airflow_delay", 20) - Set("airflow_mob_slowdown", 3) - world << "\blue [key_name(usr)] loaded ZAS preset [def]" \ No newline at end of file diff --git a/code/ZAS - vgstation/ZAS_Turfs.dm b/code/ZAS - vgstation/ZAS_Turfs.dm deleted file mode 100644 index 9b17e038541..00000000000 --- a/code/ZAS - vgstation/ZAS_Turfs.dm +++ /dev/null @@ -1,356 +0,0 @@ -atom/var/pressure_resistance = ONE_ATMOSPHERE -turf - - var/zone/zone - - assume_air(datum/gas_mixture/giver) //use this for machines to adjust air - del(giver) - return 0 - - return_air() - //Create gas mixture to hold data for passing - var/datum/gas_mixture/GM = new - - GM.oxygen = oxygen - GM.carbon_dioxide = carbon_dioxide - GM.nitrogen = nitrogen - GM.toxins = toxins - - GM.temperature = temperature - GM.update_values() - - return GM - - remove_air(amount as num) - var/datum/gas_mixture/GM = new - - var/sum = oxygen + carbon_dioxide + nitrogen + toxins - if(sum>0) - GM.oxygen = (oxygen/sum)*amount - GM.carbon_dioxide = (carbon_dioxide/sum)*amount - GM.nitrogen = (nitrogen/sum)*amount - GM.toxins = (toxins/sum)*amount - - GM.temperature = temperature - GM.update_values() - - return GM - -turf - simulated - - var/current_graphic = null - - var/tmp - datum/gas_mixture/air - - processing = 1 - - air_check_directions = 0 //Do not modify this, just add turf to air_master.tiles_to_update - - obj/fire/active_hotspot - - - proc/update_visuals() - overlays = null - - var/siding_icon_state = return_siding_icon_state() - if(siding_icon_state) - overlays += image('icons/turf/floors.dmi',siding_icon_state) - var/datum/gas_mixture/model = return_air() - switch(model.graphic) - if(1) - overlays.Add(plmaster) //TODO: Make invisible plasma an option - if(2) - overlays.Add(slmaster) - - - - New() - ..() - - if(!blocks_air) - air = new - - air.oxygen = oxygen - air.carbon_dioxide = carbon_dioxide - air.nitrogen = nitrogen - air.toxins = toxins - - air.temperature = temperature - air.update_values() - - if(air_master) - air_master.tiles_to_update.Add(src) - - else - if(air_master) - for(var/direction in cardinal) - var/turf/simulated/floor/target = get_step(src,direction) - if(istype(target)) - air_master.tiles_to_update |= target - - Del() - if(active_hotspot) - del(active_hotspot) - if(blocks_air) - for(var/direction in list(NORTH, SOUTH, EAST, WEST)) - var/turf/simulated/tile = get_step(src,direction) - if(istype(tile) && !tile.blocks_air) - air_master.tiles_to_update.Add(tile) - ..() - - assume_air(datum/gas_mixture/giver) - if(!giver) return 0 - if(zone) - zone.air.merge(giver) - return 1 - else - return ..() - - return_air() - if(zone) - return zone.air - else if(air) - return air - - else - return ..() - - remove_air(amount as num) - if(zone) - var/datum/gas_mixture/removed = null - removed = zone.air.remove(amount) - return removed - else if(air) - var/datum/gas_mixture/removed = null - removed = air.remove(amount) - - if(air.check_tile_graphic()) - update_visuals(air) - return removed - - else - return ..() - - proc/update_air_properties() - . = 1 - var/air_directions_archived = air_check_directions - air_check_directions = 0 - - for(var/direction in cardinal) - if(ZAirPass(get_step(src,direction))) - air_check_directions |= direction - - if(!zone && !blocks_air) //No zone, but not a wall. - for(var/direction in DoorDirections) //Check door directions first. - if(air_check_directions&direction) - var/turf/simulated/T = get_step(src,direction) - if(!istype(T)) - continue - if(T.zone) - T.zone.AddTurf(src) - break - if(!zone) //Still no zone - for(var/direction in CounterDoorDirections) //Check the others second. - if(air_check_directions&direction) - var/turf/simulated/T = get_step(src,direction) - if(!istype(T)) - continue - if(T.zone) - T.zone.AddTurf(src) - break - if(!zone) //No zone found, new zone! - new/zone(src) - if(!zone) //Still no zone, the floodfill determined it is not part of a larger zone. Force a zone on it. - new/zone(list(src)) - - //Check pass sanity of the connections. - if("\ref[src]" in air_master.turfs_with_connections) - for(var/connection/C in air_master.turfs_with_connections["\ref[src]"]) - air_master.connections_to_check |= C - - if(zone && !zone.rebuild) - for(var/direction in cardinal) - var/turf/T = get_step(src,direction) - if(!istype(T)) - continue - - //I can connect to air in this direction - if(air_check_directions&direction) - - //If either block air, we must look to see if the adjacent turfs need rebuilt. - if(!CanPass(null, T, 0, 0)) - - //Target blocks air - if(!T.CanPass(null, T, 0, 0)) - var/turf/NT = get_step(T, direction) - - //If that turf is in my zone still, rebuild. - if(istype(NT,/turf/simulated) && NT in zone.contents) - zone.rebuild = 1 - - //If that is an unsimulated tile in my zone, see if we need to rebuild or just remove. - else if(istype(NT) && NT in zone.unsimulated_tiles) - var/consider_rebuild = 0 - for(var/d in cardinal) - var/turf/UT = get_step(NT,d) - if(istype(UT, /turf/simulated) && UT.zone == zone && UT.CanPass(null, NT, 0, 0)) //If we find a neighboring tile that is in the same zone, check if we need to rebuild - consider_rebuild = 1 - break - if(consider_rebuild) - zone.rebuild = 1 //Gotta check if we need to rebuild, dammit - else - zone.RemoveTurf(NT) //Not adjacent to anything, and unsimulated. Goodbye~ - - //To make a closed connection through closed door. - ZConnect(T, src) - - //If I block air. - else if(T.zone && !T.zone.rebuild) - var/turf/NT = get_step(src, reverse_direction(direction)) - - //If I am splitting a zone, rebuild. - if(istype(NT,/turf/simulated) && (NT in T.zone.contents || (NT.zone && T in NT.zone.contents))) - T.zone.rebuild = 1 - - //If NT is unsimulated, parse if I should remove it or rebuild. - else if(istype(NT) && NT in T.zone.unsimulated_tiles) - var/consider_rebuild = 0 - for(var/d in cardinal) - var/turf/UT = get_step(NT,d) - if(istype(UT, /turf/simulated) && UT.zone == T.zone && UT.CanPass(null, NT, 0, 0)) //If we find a neighboring tile that is in the same zone, check if we need to rebuild - consider_rebuild = 1 - break - - //Needs rebuilt. - if(consider_rebuild) - T.zone.rebuild = 1 - - //Not adjacent to anything, and unsimulated. Goodbye~ - else - T.zone.RemoveTurf(NT) - - else - //Produce connection through open door. - ZConnect(src,T) - - //Something like a wall was built, changing the geometry. - else if(air_directions_archived&direction) - var/turf/NT = get_step(T, direction) - - //If the tile is in our own zone, and we cannot connect to it, better rebuild. - if(istype(NT,/turf/simulated) && NT in zone.contents) - zone.rebuild = 1 - - //Parse if we need to remove the tile, or rebuild the zone. - else if(istype(NT) && NT in zone.unsimulated_tiles) - var/consider_rebuild = 0 - - //Loop through all neighboring turfs to see if we should remove the turf or just rebuild. - for(var/d in cardinal) - var/turf/UT = get_step(NT,d) - - //If we find a neighboring tile that is in the same zone, rebuild - if(istype(UT, /turf/simulated) && UT.zone == zone && UT.CanPass(null, NT, 0, 0)) - consider_rebuild = 1 - break - - //The unsimulated turf is adjacent to another one of our zone's turfs, - // better rebuild to be sure we didn't get cut in twain - if(consider_rebuild && NT.zone) - NT.zone.rebuild = 1 - - //Not adjacent to anything, and unsimulated. Goodbye~ - else - zone.RemoveTurf(NT) - - if(air_check_directions) - processing = 1 - else - processing = 0 - - - - - -/turf/proc/HasDoor(turf/O) - //Checks for the presence of doors, used for zone spreading and connection. - //A positive numerical argument checks only for closed doors. - //Another turf as an argument checks for windoors between here and there. - for(var/obj/machinery/door/D in src) - if(isnum(O) && O) - if(!D.density) continue - if(istype(D,/obj/machinery/door/window)) - if(!istype(O)) - continue - if(D.dir == get_dir(D,O)) - return 1 - else - return 1 - -turf/proc/ZCanPass(turf/simulated/T, var/include_space = 0) - //Fairly standard pass checks for turfs, objects and directional windows. Also stops at the edge of space. - if(!istype(T)) - return 0 - - if(!istype(T) && !include_space) - return 0 - else - if(T.blocks_air||blocks_air) - return 0 - - for(var/obj/obstacle in src) - if(istype(obstacle, /obj/machinery/door) && !obstacle:air_properties_vary_with_direction) - continue - if(!obstacle.CanPass(null, T, 1.5, 1)) - return 0 - - for(var/obj/obstacle in T) - if(istype(obstacle, /obj/machinery/door) && !obstacle:air_properties_vary_with_direction) - continue - if(!obstacle.CanPass(null, src, 1.5, 1)) - return 0 - - return 1 - -turf/proc/ZAirPass(turf/T) - //Fairly standard pass checks for turfs, objects and directional windows. - if(!istype(T)) - return 0 - - if(T.blocks_air||blocks_air) - return 0 - - for(var/obj/obstacle in src) - if(istype(obstacle, /obj/machinery/door) && !obstacle:air_properties_vary_with_direction) - continue - if(!obstacle.CanPass(null, T, 0, 0)) - return 0 - - for(var/obj/obstacle in T) - if(istype(obstacle, /obj/machinery/door) && !obstacle:air_properties_vary_with_direction) - continue - if(!obstacle.CanPass(null, src, 0, 0)) - return 0 - - return 1 - - -/*UNUSED -/turf/proc/check_connections() - //Checks for new connections that can be made. - for(var/d in cardinal) - var/turf/simulated/T = get_step(src,d) - if(istype(T) && ( !T.zone || !T.CanPass(0,src,0,0) ) ) - continue - if(T.zone != zone) - ZConnect(src,T) - -/turf/proc/check_for_space() - //Checks for space around the turf. - for(var/d in cardinal) - var/turf/T = get_step(src,d) - if(istype(T,/turf/space) && T.CanPass(0,src,0,0)) - zone.AddSpace(T) - */ \ No newline at end of file diff --git a/code/ZAS/Airflow.dm b/code/ZAS/Airflow.dm index 87f4bda7ecf..99fb3160f2f 100644 --- a/code/ZAS/Airflow.dm +++ b/code/ZAS/Airflow.dm @@ -52,17 +52,12 @@ mob/var/tmp/last_airflow_stun = 0 mob/proc/airflow_stun() if(stat == 2) return 0 - if(last_airflow_stun > world.time - zas_settings.Get(/datum/ZAS_Setting/airflow_stun_cooldown)) return 0 + if(last_airflow_stun > world.time - vsc.airflow_stun_cooldown) return 0 if(!(status_flags & CANSTUN) && !(status_flags & CANWEAKEN)) src << "\blue You stay upright as the air rushes past you." return 0 - - if(zas_settings.Get(/datum/ZAS_Setting/airflow_push)) - if(weakened <= 0) src << "\red The sudden rush of air knocks you over!" - weakened = max(weakened,5) - last_airflow_stun = world.time - return - src << "\blue You stay upright as the air rushes past you." + if(weakened <= 0) src << "\red The sudden rush of air knocks you over!" + weakened = max(weakened,5) last_airflow_stun = world.time mob/living/silicon/airflow_stun() @@ -72,34 +67,27 @@ mob/living/carbon/metroid/airflow_stun() return mob/living/carbon/human/airflow_stun() - if(last_airflow_stun > world.time - zas_settings.Get(/datum/ZAS_Setting/airflow_stun_cooldown)) return 0 + if(last_airflow_stun > world.time - vsc.airflow_stun_cooldown) return 0 if(buckled) return 0 if(shoes) if(shoes.flags & NOSLIP) return 0 if(!(status_flags & CANSTUN) && !(status_flags & CANWEAKEN)) src << "\blue You stay upright as the air rushes past you." return 0 - - if(zas_settings.Get(/datum/ZAS_Setting/airflow_push)) - if(weakened <= 0) src << "\red The sudden rush of air knocks you over!" - weakened = max(weakened,rand(1,5)) - last_airflow_stun = world.time - return - src << "\blue You stay upright as the air rushes past you." + if(weakened <= 0) src << "\red The sudden rush of air knocks you over!" + weakened = max(weakened,rand(1,5)) last_airflow_stun = world.time atom/movable/proc/check_airflow_movable(n) - if(!zas_settings.Get(/datum/ZAS_Setting/airflow_push)) - return 0 - if(anchored && !ismob(src)) - return 0 - if(!istype(src,/obj/item) && n < zas_settings.Get(/datum/ZAS_Setting/airflow_dense_pressure)) - return 0 + + if(anchored && !ismob(src)) return 0 + + if(!istype(src,/obj/item) && n < vsc.airflow_dense_pressure) return 0 return 1 mob/check_airflow_movable(n) - if(n < zas_settings.Get(/datum/ZAS_Setting/airflow_heavy_pressure)) + if(n < vsc.airflow_heavy_pressure) return 0 return 1 @@ -114,11 +102,11 @@ obj/item/check_airflow_movable(n) . = ..() switch(w_class) if(2) - if(n < zas_settings.Get(/datum/ZAS_Setting/airflow_lightest_pressure)) return 0 + if(n < vsc.airflow_lightest_pressure) return 0 if(3) - if(n < zas_settings.Get(/datum/ZAS_Setting/airflow_light_pressure)) return 0 + if(n < vsc.airflow_light_pressure) return 0 if(4,5) - if(n < zas_settings.Get(/datum/ZAS_Setting/airflow_medium_pressure)) return 0 + if(n < vsc.airflow_medium_pressure) return 0 //The main airflow code. Called by zone updates. //Zones A and B are air zones. n represents the amount of air moved. @@ -128,7 +116,7 @@ proc/Airflow(zone/A, zone/B) var/n = B.air.return_pressure() - A.air.return_pressure() //Don't go any further if n is lower than the lowest value needed for airflow. - if(abs(n) < zas_settings.Get(/datum/ZAS_Setting/airflow_lightest_pressure)) return + if(abs(n) < vsc.airflow_lightest_pressure) return //These turfs are the midway point between A and B, and will be the destination point for thrown objects. var/list/connection/connections_A = A.connections @@ -153,52 +141,53 @@ proc/Airflow(zone/A, zone/B) var/list/temporary_pplz = air_sucked air_sucked = air_repelled air_repelled = temporary_pplz - if(zas_settings.Get(/datum/ZAS_Setting/airflow_push)) // If enabled - for(var/atom/movable/M in air_sucked) - if(M.last_airflow > world.time - zas_settings.Get(/datum/ZAS_Setting/airflow_delay)) continue - //Check for knocking people over - if(ismob(M) && n > zas_settings.Get(/datum/ZAS_Setting/airflow_stun_pressure)) - if(M:status_flags & GODMODE) continue - M:airflow_stun() + for(var/atom/movable/M in air_sucked) - if(M.check_airflow_movable(n)) + if(M.last_airflow > world.time - vsc.airflow_delay) continue - //Check for things that are in range of the midpoint turfs. - var/list/close_turfs = list() - for(var/turf/U in connected_turfs) - if(M in range(U)) close_turfs += U - if(!close_turfs.len) continue + //Check for knocking people over + if(ismob(M) && n > vsc.airflow_stun_pressure) + if(M:status_flags & GODMODE) continue + M:airflow_stun() - //If they're already being tossed, don't do it again. - if(!M.airflow_speed) + if(M.check_airflow_movable(n)) - M.airflow_dest = pick(close_turfs) //Pick a random midpoint to fly towards. + //Check for things that are in range of the midpoint turfs. + var/list/close_turfs = list() + for(var/turf/U in connected_turfs) + if(M in range(U)) close_turfs += U + if(!close_turfs.len) continue - spawn M.GotoAirflowDest(abs(n)/5) + //If they're already being tossed, don't do it again. + if(!M.airflow_speed) - //Do it again for the stuff in the other zone, making it fly away. - for(var/atom/movable/M in air_repelled) + M.airflow_dest = pick(close_turfs) //Pick a random midpoint to fly towards. - if(M.last_airflow > world.time - zas_settings.Get(/datum/ZAS_Setting/airflow_delay)) continue + spawn M.GotoAirflowDest(abs(n)/5) - if(ismob(M) && abs(n) > zas_settings.Get(/datum/ZAS_Setting/airflow_medium_pressure)) - if(M:status_flags & GODMODE) continue - M:airflow_stun() + //Do it again for the stuff in the other zone, making it fly away. + for(var/atom/movable/M in air_repelled) - if(M.check_airflow_movable(abs(n))) + if(M.last_airflow > world.time - vsc.airflow_delay) continue - var/list/close_turfs = list() - for(var/turf/U in connected_turfs) - if(M in range(U)) close_turfs += U - if(!close_turfs.len) continue + if(ismob(M) && abs(n) > vsc.airflow_medium_pressure) + if(M:status_flags & GODMODE) continue + M:airflow_stun() - //If they're already being tossed, don't do it again. - if(!M.airflow_speed) + if(M.check_airflow_movable(abs(n))) - M.airflow_dest = pick(close_turfs) //Pick a random midpoint to fly towards. + var/list/close_turfs = list() + for(var/turf/U in connected_turfs) + if(M in range(U)) close_turfs += U + if(!close_turfs.len) continue - spawn M.RepelAirflowDest(abs(n)/5) + //If they're already being tossed, don't do it again. + if(!M.airflow_speed) + + M.airflow_dest = pick(close_turfs) //Pick a random midpoint to fly towards. + + spawn M.RepelAirflowDest(abs(n)/5) proc/AirflowSpace(zone/A) @@ -207,34 +196,34 @@ proc/AirflowSpace(zone/A) var/n = A.air.return_pressure() //Here, n is determined by only the pressure in the room. - if(n < zas_settings.Get(/datum/ZAS_Setting/airflow_lightest_pressure)) return + if(n < vsc.airflow_lightest_pressure) return var/list/connected_turfs = A.unsimulated_tiles //The midpoints are now all the space connections. var/list/pplz = A.movables() //We only need to worry about things in the zone, not things in space. - if(zas_settings.Get(/datum/ZAS_Setting/airflow_push)) // If enabled - for(var/atom/movable/M in pplz) - if(M.last_airflow > world.time - zas_settings.Get(/datum/ZAS_Setting/airflow_delay)) continue + for(var/atom/movable/M in pplz) - if(ismob(M) && n > zas_settings.Get(/datum/ZAS_Setting/airflow_stun_pressure)) - var/mob/O = M - if(O.status_flags & GODMODE) continue - O.airflow_stun() + if(M.last_airflow > world.time - vsc.airflow_delay) continue - if(M.check_airflow_movable(n)) + if(ismob(M) && n > vsc.airflow_stun_pressure) + var/mob/O = M + if(O.status_flags & GODMODE) continue + O.airflow_stun() - var/list/close_turfs = list() - for(var/turf/U in connected_turfs) - if(M in range(U)) close_turfs += U - if(!close_turfs.len) continue + if(M.check_airflow_movable(n)) - //If they're already being tossed, don't do it again. - if(!M.airflow_speed) + var/list/close_turfs = list() + for(var/turf/U in connected_turfs) + if(M in range(U)) close_turfs += U + if(!close_turfs.len) continue - M.airflow_dest = pick(close_turfs) //Pick a random midpoint to fly towards. - spawn - if(M) M.GotoAirflowDest(n/10) - //Sometimes shit breaks, and M isn't there after the spawn. + //If they're already being tossed, don't do it again. + if(!M.airflow_speed) + + M.airflow_dest = pick(close_turfs) //Pick a random midpoint to fly towards. + spawn + if(M) M.GotoAirflowDest(n/10) + //Sometimes shit breaks, and M isn't there after the spawn. /atom/movable/var/tmp/turf/airflow_dest @@ -243,10 +232,9 @@ proc/AirflowSpace(zone/A) /atom/movable/var/tmp/last_airflow = 0 /atom/movable/proc/GotoAirflowDest(n) - if(!zas_settings.Get(/datum/ZAS_Setting/airflow_push)) return // If not enabled, fuck it. if(!airflow_dest) return if(airflow_speed < 0) return - if(last_airflow > world.time - zas_settings.Get(/datum/ZAS_Setting/airflow_delay)) return + if(last_airflow > world.time - vsc.airflow_delay) return if(airflow_speed) airflow_speed = n/max(get_dist(src,airflow_dest),1) return @@ -280,7 +268,7 @@ proc/AirflowSpace(zone/A) while(airflow_speed > 0) if(airflow_speed <= 0) return airflow_speed = min(airflow_speed,15) - airflow_speed -= zas_settings.Get(/datum/ZAS_Setting/airflow_speed_decay) + airflow_speed -= vsc.airflow_speed_decay if(airflow_speed > 7) if(airflow_time++ >= airflow_speed - 7) if(od) @@ -300,7 +288,7 @@ proc/AirflowSpace(zone/A) return step_towards(src, src.airflow_dest) if(ismob(src) && src:client) - src:client:move_delay = world.time + zas_settings.Get(/datum/ZAS_Setting/airflow_mob_slowdown) + src:client:move_delay = world.time + vsc.airflow_mob_slowdown airflow_dest = null airflow_speed = 0 airflow_time = 0 @@ -309,10 +297,9 @@ proc/AirflowSpace(zone/A) /atom/movable/proc/RepelAirflowDest(n) - if(!zas_settings.Get(/datum/ZAS_Setting/airflow_push)) return // If not enabled, fuck it. if(!airflow_dest) return if(airflow_speed < 0) return - if(last_airflow > world.time - zas_settings.Get(/datum/ZAS_Setting/airflow_delay)) return + if(last_airflow > world.time - vsc.airflow_delay) return if(airflow_speed) airflow_speed = n/max(get_dist(src,airflow_dest),1) return @@ -346,7 +333,7 @@ proc/AirflowSpace(zone/A) while(airflow_speed > 0) if(airflow_speed <= 0) return airflow_speed = min(airflow_speed,15) - airflow_speed -= zas_settings.Get(/datum/ZAS_Setting/airflow_speed_decay) + airflow_speed -= vsc.airflow_speed_decay if(airflow_speed > 7) if(airflow_time++ >= airflow_speed - 7) sleep(1 * tick_multiplier) @@ -360,7 +347,7 @@ proc/AirflowSpace(zone/A) return step_towards(src, src.airflow_dest) if(ismob(src) && src:client) - src:client:move_delay = world.time + zas_settings.Get(/datum/ZAS_Setting/airflow_mob_slowdown) + src:client:move_delay = world.time + vsc.airflow_mob_slowdown airflow_dest = null airflow_speed = 0 airflow_time = 0 @@ -382,14 +369,14 @@ atom/movable/proc/airflow_hit(atom/A) mob/airflow_hit(atom/A) for(var/mob/M in hearers(src)) M.show_message("\red \The [src] slams into \a [A]!",1,"\red You hear a loud slam!",2) - //playsound(src.loc, "smash.ogg", 25, 1, -1) + playsound(src.loc, "smash.ogg", 25, 1, -1) weakened = max(weakened, (istype(A,/obj/item) ? A:w_class : rand(1,5))) //Heheheh . = ..() obj/airflow_hit(atom/A) for(var/mob/M in hearers(src)) M.show_message("\red \The [src] slams into \a [A]!",1,"\red You hear a loud slam!",2) - //playsound(src.loc, "smash.ogg", 25, 1, -1) + playsound(src.loc, "smash.ogg", 25, 1, -1) . = ..() obj/item/airflow_hit(atom/A) @@ -399,13 +386,13 @@ obj/item/airflow_hit(atom/A) mob/living/carbon/human/airflow_hit(atom/A) // for(var/mob/M in hearers(src)) // M.show_message("\red [src] slams into [A]!",1,"\red You hear a loud slam!",2) - //playsound(src.loc, "punch", 25, 1, -1) + playsound(src.loc, "punch", 25, 1, -1) loc:add_blood(src) if (src.wear_suit) src.wear_suit.add_blood(src) if (src.w_uniform) src.w_uniform.add_blood(src) - var/b_loss = airflow_speed * zas_settings.Get(/datum/ZAS_Setting/airflow_damage) + var/b_loss = airflow_speed * vsc.airflow_damage var/blocked = run_armor_check("head","melee") apply_damage(b_loss/3, BRUTE, "head", blocked, 0, "Airflow") @@ -416,19 +403,18 @@ mob/living/carbon/human/airflow_hit(atom/A) blocked = run_armor_check("groin","melee") apply_damage(b_loss/3, BRUTE, "groin", blocked, 0, "Airflow") - if(zas_settings.Get(/datum/ZAS_Setting/airflow_push)) - if(airflow_speed > 10) - paralysis += round(airflow_speed * zas_settings.Get(/datum/ZAS_Setting/airflow_stun)) - stunned = max(stunned,paralysis + 3) - else - stunned += round(airflow_speed * zas_settings.Get(/datum/ZAS_Setting/airflow_stun)/2) - + if(airflow_speed > 10) + paralysis += round(airflow_speed * vsc.airflow_stun) + stunned = max(stunned,paralysis + 3) + else + stunned += round(airflow_speed * vsc.airflow_stun/2) . = ..() zone/proc/movables() . = list() for(var/turf/T in contents) for(var/atom/A in T) - if(istype(A, /obj/effect) || isobserver(A) || istype(A, /mob/camera)) +// if(istype(A, /obj/effect) || istype(A, /mob/aiEye)) + if(istype(A, /obj/effect) || istype(A, /mob/camera/aiEye)) continue . += A diff --git a/code/ZAS/Connection.dm b/code/ZAS/Connection.dm index 8a919d50435..1bb8f9ca54d 100644 --- a/code/ZAS/Connection.dm +++ b/code/ZAS/Connection.dm @@ -13,68 +13,62 @@ Indirect connections will not merge the two zones after they reach equilibrium. var/zone/zone_A var/zone/zone_B - var/ref_A - var/ref_B - var/indirect = CONNECTION_DIRECT //If the connection is purely indirect, the zones should not join. - var/last_updated //The tick at which this was last updated. - - var/no_zone_count = 0 - - /connection/New(turf/T,turf/O) + . = ..() + A = T B = O + if(A.zone && B.zone) - if(!A.zone.connections) A.zone.connections = list() + 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() + 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] + if(A in air_master.turfs_with_connections) + var/list/connections = air_master.turfs_with_connections[A] connections.Add(src) else - air_master.turfs_with_connections[ref_A] = list(src) + air_master.turfs_with_connections[A] = list(src) - if(ref_B in air_master.turfs_with_connections) - var/list/connections = air_master.turfs_with_connections[ref_B] + if(B in air_master.turfs_with_connections) + var/list/connections = air_master.turfs_with_connections[B] connections.Add(src) else - air_master.turfs_with_connections[ref_B] = list(src) + air_master.turfs_with_connections[B] = list(src) if(A.CanPass(null, B, 0, 0)) - ConnectZones(A.zone, B.zone, 1) - - if(A.HasDoor(B) || B.HasDoor(A)) + if(!A.CanPass(null, B, 1.5, 1)) indirect = CONNECTION_INDIRECT + ConnectZones(A.zone, B.zone, 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) + SoftDelete() /connection/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] + if(B in air_master.turfs_with_connections) + var/list/connections = air_master.turfs_with_connections[B] connections.Remove(src) - if(ref_A in air_master.turfs_with_connections) - var/list/connections = air_master.turfs_with_connections[ref_A] + if(A in air_master.turfs_with_connections) + var/list/connections = air_master.turfs_with_connections[A] connections.Remove(src) //Remove connection from zones. @@ -104,13 +98,52 @@ Indirect connections will not merge the two zones after they reach equilibrium. //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) + DisconnectZones(zone_A, zone_B) //Finally, preform actual deletion. . = ..() +/connection/proc/SoftDelete() + //remove connections from master lists. + if(B in air_master.turfs_with_connections) + var/list/connections = air_master.turfs_with_connections[B] + connections.Remove(src) + + if(A in air_master.turfs_with_connections) + var/list/connections = air_master.turfs_with_connections[A] + connections.Remove(src) + + //Remove connection from zones. + if(A) + if(A.zone && A.zone.connections) + A.zone.connections.Remove(src) + if(!A.zone.connections.len) + A.zone.connections = null + + if(istype(zone_A) && (!A || A.zone != zone_A)) + if(zone_A.connections) + zone_A.connections.Remove(src) + if(!zone_A.connections.len) + zone_A.connections = null + + if(B) + if(B.zone && B.zone.connections) + B.zone.connections.Remove(src) + if(!B.zone.connections.len) + B.zone.connections = null + + if(istype(zone_B) && (!B || B.zone != zone_B)) + if(zone_B.connections) + zone_B.connections.Remove(src) + if(!zone_B.connections.len) + zone_B.connections = null + + //Disconnect zones while handling unusual conditions. + // e.g. loss of a zone on a turf + DisconnectZones(zone_A, zone_B) + + /connection/proc/ConnectZones(var/zone/zone_1, var/zone/zone_2, open = 0) //Sanity checking @@ -140,6 +173,18 @@ Indirect connections will not merge the two zones after they reach equilibrium. zone_2.connected_zones += zone_1 zone_2.connected_zones[zone_1] = 1 + if(open == CONNECTION_DIRECT) + if(!zone_1.direct_connections) + zone_1.direct_connections = list(src) + else + zone_1.direct_connections += src + + if(!zone_2.direct_connections) + zone_2.direct_connections = list(src) + else + zone_2.direct_connections += src + + //Handle closed connections. else @@ -163,6 +208,11 @@ Indirect connections will not merge the two zones after they reach equilibrium. zone_2.closed_connection_zones += zone_1 zone_2.closed_connection_zones[zone_1] = 1 + if(zone_1.status == ZONE_SLEEPING) + zone_1.SetStatus(ZONE_ACTIVE) + + if(zone_2.status == ZONE_SLEEPING) + zone_2.SetStatus(ZONE_ACTIVE) /connection/proc/DisconnectZones(var/zone/zone_1, var/zone/zone_2) //Sanity checking @@ -193,6 +243,15 @@ Indirect connections will not merge the two zones after they reach equilibrium. if(!zone_2.connected_zones.len) zone_2.connected_zones = null + if(indirect == CONNECTION_DIRECT) + zone_1.direct_connections -= src + if(!zone_1.direct_connections.len) + zone_1.direct_connections = null + + zone_2.direct_connections -= src + if(!zone_2.direct_connections.len) + zone_2.direct_connections = null + else //Handle disconnection of closed zones. if( (zone_1 in zone_2.closed_connection_zones) || (zone_2 in zone_1.closed_connection_zones) ) @@ -222,35 +281,23 @@ Indirect connections will not merge the two zones after they reach equilibrium. //Check sanity: existance of turfs if(!A || !B) - del src + SoftDelete() + return + + //Check sanity: loss of zone + if(!A.zone || !B.zone) + SoftDelete() + return //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 + SoftDelete() + return //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 - - -/connection/proc/CheckPassSanity() - //Sanity check, first. - Cleanup() - if(A.zone && B.zone) //If no walls are blocking us... @@ -263,7 +310,7 @@ Indirect connections will not merge the two zones after they reach equilibrium. //Make and remove connections to let air pass. if(indirect == CONNECTION_CLOSED) DisconnectZones(A.zone, B.zone) - ConnectZones(A.zone, B.zone, 1) + ConnectZones(A.zone, B.zone, door_pass + 1) if(door_pass) indirect = CONNECTION_DIRECT @@ -278,7 +325,8 @@ Indirect connections will not merge the two zones after they reach equilibrium. //If I can no longer pass air, better delete else - del src + SoftDelete() + return /connection/proc/Sanitize() //If the zones change on connected turfs, update it. @@ -294,9 +342,6 @@ Indirect connections will not merge the two zones after they reach equilibrium. 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. @@ -400,4 +445,4 @@ Indirect connections will not merge the two zones after they reach equilibrium. #undef CONNECTION_DIRECT #undef CONNECTION_INDIRECT -#undef CONNECTION_CLOSED \ No newline at end of file +#undef CONNECTION_CLOSED diff --git a/code/ZAS/Debug.dm b/code/ZAS/Debug.dm index 6586cbaaecf..5ac704cf9fa 100644 --- a/code/ZAS/Debug.dm +++ b/code/ZAS/Debug.dm @@ -1,3 +1,14 @@ +client/proc/ZoneTick() + set category = "Debug" + set name = "Process Atmos" + + var/result = air_master.Tick() + if(result) + src << "Sucessfully Processed." + + else + src << "Failed to process! ([air_master.tick_progress])" + client/proc/Zone_Info(turf/T as null|turf) set category = "Debug" @@ -115,8 +126,88 @@ zone/proc/DebugDisplay(client/client) client.images -= client.zone_debug_images[src] client.zone_debug_images.Remove(src) - for(var/zone/Z in zones) - if(Z.air == air && Z != src) - var/turf/zloc = pick(Z.contents) - client << "\red Illegal air datum shared by: [zloc.loc.name]" + if(air_master) + for(var/zone/Z in air_master.zones) + if(Z.air == air && Z != src) + var/turf/zloc = pick(Z.contents) + client << "\red Illegal air datum shared by: [zloc.loc.name]" + +client/proc/TestZASRebuild() +// var/turf/turf = get_turf(mob) + var/zone/current_zone = mob.loc:zone + if(!current_zone) + src << "There is no zone there!" + return + + var/list/current_adjacents = list() + var/list/overlays = list() + var/adjacent_id + var/lowest_id + + var/list/identical_ids = list() + var/list/turfs = current_zone.contents.Copy() + var/current_identifier = 1 + + for(var/turf/simulated/current in turfs) + lowest_id = null + current_adjacents = list() + + for(var/direction in cardinal) + var/turf/simulated/adjacent = get_step(current, direction) + if(!current.ZAirPass(adjacent)) + continue + if(turfs.Find(adjacent)) + current_adjacents += adjacent + adjacent_id = turfs[adjacent] + + if(adjacent_id && (!lowest_id || adjacent_id < lowest_id)) + lowest_id = adjacent_id + + if(!lowest_id) + lowest_id = current_identifier++ + identical_ids += lowest_id + overlays += image('icons/misc/debug_rebuild.dmi',, "[lowest_id]") + + for(var/turf/simulated/adjacent in current_adjacents) + adjacent_id = turfs[adjacent] + if(adjacent_id != lowest_id) + if(adjacent_id) + adjacent.overlays -= overlays[adjacent_id] + identical_ids[adjacent_id] = lowest_id + + turfs[adjacent] = lowest_id + adjacent.overlays += overlays[lowest_id] + + sleep(5) + + if(turfs[current]) + current.overlays -= overlays[turfs[current]] + turfs[current] = lowest_id + current.overlays += overlays[lowest_id] + sleep(5) + + var/list/final_arrangement = list() + + for(var/turf/simulated/current in turfs) + current_identifier = identical_ids[turfs[current]] + current.overlays -= overlays[turfs[current]] + current.overlays += overlays[current_identifier] + sleep(5) + + if( current_identifier > final_arrangement.len ) + final_arrangement.len = current_identifier + final_arrangement[current_identifier] = list(current) + + else + final_arrangement[current_identifier] += current + + //lazy but fast + final_arrangement.Remove(null) + + src << "There are [final_arrangement.len] unique segments." + + for(var/turf/current in turfs) + current.overlays -= overlays + + return final_arrangement \ No newline at end of file diff --git a/code/ZAS/FEA_gas_mixture.dm b/code/ZAS/FEA_gas_mixture.dm index 37c53c8feda..3eccad7e913 100644 --- a/code/ZAS/FEA_gas_mixture.dm +++ b/code/ZAS/FEA_gas_mixture.dm @@ -8,21 +8,12 @@ What are the archived variables for? #define SPECIFIC_HEAT_AIR 20 #define SPECIFIC_HEAT_CDO 30 #define HEAT_CAPACITY_CALCULATION(oxygen,carbon_dioxide,nitrogen,toxins) \ - (carbon_dioxide*SPECIFIC_HEAT_CDO + (oxygen+nitrogen)*SPECIFIC_HEAT_AIR + toxins*SPECIFIC_HEAT_TOXIN) + max(0, carbon_dioxide * SPECIFIC_HEAT_CDO + (oxygen + nitrogen) * SPECIFIC_HEAT_AIR + toxins * SPECIFIC_HEAT_TOXIN) #define MINIMUM_HEAT_CAPACITY 0.0003 #define QUANTIZE(variable) (round(variable,0.0001)) #define TRANSFER_FRACTION 5 //What fraction (1/#) of the air difference to try and transfer -#define TEMPERATURE_ICE_FORMATION 273.15 // 273 kelvin is the freezing point of water. -#define MIN_PRESSURE_ICE_FORMATION 10 // 10kPa should be okay - -#define GRAPHICS_PLASMA 1 -#define GRAPHICS_N2O 2 -#define GRAPHICS_REAGENTS 4 // Not used. Yet. -#define GRAPHICS_COLD 8 - - /datum/gas/sleeping_agent/specific_heat = 40 //These are used for the "Trace Gases" stuff, but is buggy. /datum/gas/oxygen_agent_b/specific_heat = 300 @@ -52,7 +43,7 @@ What are the archived variables for? //Size of the group this gas_mixture is representing. //=1 for singletons - var/graphics=0 + var/graphic var/list/datum/gas/trace_gases = list() //Seemed to be a good idea that was abandoned @@ -63,9 +54,11 @@ What are the archived variables for? var/tmp/temperature_archived - var/tmp/graphics_archived = 0 + var/tmp/graphic_archived = 0 var/tmp/fuel_burnt = 0 + var/reacting = 0 + //FOR THE LOVE OF GOD PLEASE USE THIS PROC //Call it with negative numbers to remove gases. @@ -90,7 +83,7 @@ What are the archived variables for? update_values() return -//tg seems to like using these a lot + //tg seems to like using these a lot /datum/gas_mixture/proc/return_temperature() return temperature @@ -114,7 +107,7 @@ What are the archived variables for? var/heat_capacity = HEAT_CAPACITY_CALCULATION(oxygen,carbon_dioxide,nitrogen,toxins) - if(trace_gases && trace_gases.len) //sanity check because somehow the tracegases gets nulled? + if(trace_gases.len) for(var/datum/gas/trace_gas in trace_gases) heat_capacity += trace_gas.moles*trace_gas.specific_heat @@ -198,30 +191,17 @@ What are the archived variables for? //Inputs: None //Outputs: 1 if graphic changed, 0 if unchanged - graphics = 0 - - // If configured and cold, maek ice - if(zas_settings.Get(/datum/ZAS_Setting/ice_formation)) - if(temperature <= TEMPERATURE_ICE_FORMATION && return_pressure()>MIN_PRESSURE_ICE_FORMATION) - // If we're just forming, do a probability check. Otherwise, KEEP IT ON~ - // This ordering will hopefully keep it from sampling random noise every damn tick. - //if(was_icy || (!was_icy && prob(25))) - graphics |= GRAPHICS_COLD - + graphic = 0 if(toxins > MOLES_PLASMA_VISIBLE) - graphics |= GRAPHICS_PLASMA - if(length(trace_gases)) + graphic = 1 + else if(length(trace_gases)) var/datum/gas/sleeping_agent = locate(/datum/gas/sleeping_agent) in trace_gases if(sleeping_agent && (sleeping_agent.moles > 1)) - graphics |= GRAPHICS_N2O + graphic = 2 + else + graphic = 0 - /* - var/datum/gas/reagent = exact_locate(/datum/gas/reagent,trace_gases) - if(reagent && (reagent.moles > 0.1)) - graphics |= GRAPHICS_REAGENTS - */ - - return graphics != graphics_archived + return graphic != graphic_archived /datum/gas_mixture/proc/react(atom/dump_location) //Purpose: Calculating if it is possible for a fire to occur in the airmix @@ -229,14 +209,13 @@ What are the archived variables for? //Inputs: None //Outputs: If a fire occured - var/reacting = 0 //set to 1 if a notable reaction occured (used by pipe_network) + //set to 1 if a notable reaction occured (used by pipe_network) - if(temperature > FIRE_MINIMUM_TEMPERATURE_TO_EXIST) - if(zburn(null) > 0) - reacting = 1 + zburn(null) return reacting +/* /datum/gas_mixture/proc/fire() //Purpose: Calculating any fire reactions. //Called by: react() (See above) @@ -245,7 +224,7 @@ What are the archived variables for? return zburn(null) - /*var/energy_released = 0 + var/energy_released = 0 var/old_heat_capacity = heat_capacity() var/datum/gas/volatile_fuel/fuel_store = locate(/datum/gas/volatile_fuel) in trace_gases @@ -320,7 +299,7 @@ What are the archived variables for? temperature_archived = temperature - graphics_archived = graphics + graphic_archived = graphic return 1 @@ -395,10 +374,6 @@ What are the archived variables for? //Inputs: How many moles to remove. //Outputs: Removed air. - // Fix a singuloth problem - if(group_multiplier==0) - return null - var/sum = total_moles() amount = min(amount,sum) //Can not take more air than tile has! if(amount <= 0) @@ -410,7 +385,7 @@ What are the archived variables for? removed.oxygen = QUANTIZE((oxygen/sum)*amount) removed.nitrogen = QUANTIZE((nitrogen/sum)*amount) removed.carbon_dioxide = QUANTIZE((carbon_dioxide/sum)*amount) - removed.toxins = QUANTIZE((toxins/sum)*amount) + removed.toxins = QUANTIZE(((toxins/sum)*amount)) oxygen -= removed.oxygen/group_multiplier nitrogen -= removed.nitrogen/group_multiplier @@ -422,8 +397,8 @@ What are the archived variables for? var/datum/gas/corresponding = new trace_gas.type() removed.trace_gases += corresponding - corresponding.moles = (trace_gas.moles/sum)*amount - trace_gas.moles -= corresponding.moles/group_multiplier + corresponding.moles = ((trace_gas.moles/sum)*amount) + trace_gas.moles -= (corresponding.moles/group_multiplier) removed.temperature = temperature update_values() @@ -990,6 +965,7 @@ What are the archived variables for? //Outputs: 1 if can rebuild, 0 if not. if(!sample) return 0 + if((abs(oxygen-sample.oxygen) > MINIMUM_AIR_TO_SUSPEND) && \ ((oxygen < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.oxygen) || (oxygen > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.oxygen))) return 0 @@ -997,39 +973,60 @@ What are the archived variables for? ((nitrogen < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.nitrogen) || (nitrogen > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.nitrogen))) return 0 if((abs(carbon_dioxide-sample.carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && \ - ((carbon_dioxide < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.carbon_dioxide) || (oxygen > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.carbon_dioxide))) + ((carbon_dioxide < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.carbon_dioxide) || (carbon_dioxide > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.carbon_dioxide))) return 0 if((abs(toxins-sample.toxins) > MINIMUM_AIR_TO_SUSPEND) && \ ((toxins < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.toxins) || (toxins > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.toxins))) return 0 + if(total_moles() > MINIMUM_AIR_TO_SUSPEND) if((abs(temperature-sample.temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) && \ ((temperature < (1-MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND)*sample.temperature) || (temperature > (1+MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND)*sample.temperature))) //world << "temp fail [temperature] & [sample.temperature]" return 0 - + var/check_moles if(sample.trace_gases.len) for(var/datum/gas/trace_gas in sample.trace_gases) - if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND) - var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases - if(corresponding) - if((abs(trace_gas.moles - corresponding.moles) > MINIMUM_AIR_TO_SUSPEND) && \ - ((corresponding.moles < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*trace_gas.moles) || (corresponding.moles > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*trace_gas.moles))) - return 0 - else - return 0 + var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases + if(corresponding) + check_moles = corresponding.moles + else + check_moles = 0 + + if((abs(trace_gas.moles - check_moles) > MINIMUM_AIR_TO_SUSPEND) && \ + ((check_moles < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*trace_gas.moles) || (check_moles > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*trace_gas.moles))) + return 0 if(trace_gases.len) for(var/datum/gas/trace_gas in trace_gases) - if(trace_gas.moles > MINIMUM_AIR_TO_SUSPEND) - var/datum/gas/corresponding = locate(trace_gas.type) in sample.trace_gases - if(corresponding) - if((abs(trace_gas.moles - corresponding.moles) > MINIMUM_AIR_TO_SUSPEND) && \ - ((trace_gas.moles < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*corresponding.moles) || (trace_gas.moles > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*corresponding.moles))) - return 0 - else - return 0 + var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases + if(corresponding) + check_moles = corresponding.moles + else + check_moles = 0 + + if((abs(trace_gas.moles - check_moles) > MINIMUM_AIR_TO_SUSPEND) && \ + ((trace_gas.moles < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*check_moles) || (trace_gas.moles > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*check_moles))) + return 0 + + return 1 + +/datum/gas_mixture/proc/add(datum/gas_mixture/right_side) + oxygen += right_side.oxygen + carbon_dioxide += right_side.carbon_dioxide + nitrogen += right_side.nitrogen + toxins += right_side.toxins + + if(trace_gases.len || right_side.trace_gases.len) + for(var/datum/gas/trace_gas in right_side.trace_gases) + var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases + if(!corresponding) + corresponding = new trace_gas.type() + trace_gases += corresponding + corresponding.moles += trace_gas.moles + + update_values() return 1 /datum/gas_mixture/proc/subtract(datum/gas_mixture/right_side) @@ -1038,18 +1035,42 @@ What are the archived variables for? //Inputs: Gas mix to remove //Outputs: 1 - oxygen -= right_side.oxygen - carbon_dioxide -= right_side.carbon_dioxide - nitrogen -= right_side.nitrogen - toxins -= right_side.toxins + oxygen = max(oxygen - right_side.oxygen) + carbon_dioxide = max(carbon_dioxide - right_side.carbon_dioxide) + nitrogen = max(nitrogen - right_side.nitrogen) + toxins = max(toxins - right_side.toxins) - if((trace_gases.len > 0)||(right_side.trace_gases.len > 0)) + if(trace_gases.len || right_side.trace_gases.len) for(var/datum/gas/trace_gas in right_side.trace_gases) var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases - if(!corresponding) - corresponding = new trace_gas.type() - trace_gases += corresponding + if(corresponding) + corresponding.moles = max(0, corresponding.moles - trace_gas.moles) - corresponding.moles -= trace_gas.moles update_values() - return 1 \ No newline at end of file + return 1 + +/datum/gas_mixture/proc/multiply(factor) + oxygen *= factor + carbon_dioxide *= factor + nitrogen *= factor + toxins *= factor + + if(trace_gases && trace_gases.len) + for(var/datum/gas/trace_gas in trace_gases) + trace_gas.moles *= factor + + update_values() + return 1 + +/datum/gas_mixture/proc/divide(factor) + oxygen /= factor + carbon_dioxide /= factor + nitrogen /= factor + toxins /= factor + + if(trace_gases && trace_gases.len) + for(var/datum/gas/trace_gas in trace_gases) + trace_gas.moles /= factor + + update_values() + return 1 diff --git a/code/ZAS/FEA_system.dm b/code/ZAS/FEA_system.dm index c2a33ad99db..5a386d5959e 100644 --- a/code/ZAS/FEA_system.dm +++ b/code/ZAS/FEA_system.dm @@ -50,10 +50,8 @@ Important Procedures air_master.process() This first processes the air_master update/rebuild lists then processes all groups and tiles for air calculations - */ -var/kill_air = 0 var/tick_multiplier = 2 atom/proc/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) @@ -87,17 +85,32 @@ atom/proc/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) var/datum/controller/air_system/air_master -/datum/controller/air_system/ - //Geoemetry lists +/datum/controller/air_system + //Geometry lists var/list/turfs_with_connections = list() var/list/active_hotspots = list() //Special functions lists + var/reconsidering_zones = FALSE var/list/tiles_to_reconsider_zones = list() + var/list/tiles_to_reconsider_alternate //Geometry updates lists + var/updating_tiles = FALSE var/list/tiles_to_update = list() + var/list/tiles_to_update_alternate + + var/checking_connections = FALSE var/list/connections_to_check = list() + var/list/connections_to_check_alternate + + var/list/potential_intrazone_connections = list() + + //Zone lists + var/list/active_zones = list() + var/list/zones_needing_rebuilt = list() + var/list/zones = list() + var/current_cycle = 0 var/update_delay = 5 //How long between check should it try to process atmos again. @@ -106,20 +119,7 @@ var/datum/controller/air_system/air_master var/tick_progress = 0 -/* process() - //Call this to process air movements for a cycle - - process_rebuild_select_groups() - //Used by process() - //Warning: Do not call this - - rebuild_group(datum/air_group) - //Used by process_rebuild_select_groups() - //Warning: Do not call this, add the group to air_master.groups_to_rebuild instead - */ - - -/datum/controller/air_system/proc/setup() +/datum/controller/air_system/proc/Setup() //Purpose: Call this at the start to setup air groups geometry // (Warning: Very processor intensive but only must be done once per round) //Called by: Gameticker/Master controller @@ -147,10 +147,11 @@ var/datum/controller/air_system/air_master Total Simulated Turfs: [simulated_turf_count] Total Zones: [zones.len] Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_count]"} - /* - spawn start() -/datum/controller/air_system/proc/start() +// spawn Start() + + +/datum/controller/air_system/proc/Start() //Purpose: This is kicked off by the master controller, and controls the processing of all atmosphere. //Called by: Master controller //Inputs: None. @@ -160,62 +161,196 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun set background = 1 while(1) - if(!kill_air) - current_cycle++ - var/success = tick() //Changed so that a runtime does not crash the ticker. + if(!air_processing_killed) + var/success = Tick() //Changed so that a runtime does not crash the ticker. if(!success) //Runtimed. failed_ticks++ if(failed_ticks > 20) world << "ERROR IN ATMOS TICKER. Killing air simulation!" - kill_air = 1 + air_processing_killed = 1 sleep(max(5,update_delay*tick_multiplier)) - */ -/datum/controller/air_system/proc/tick() + +/datum/controller/air_system/proc/Tick() . = 1 //Set the default return value, for runtime detection. - tick_progress = "update_air_properties" - if(tiles_to_update.len) //If there are tiles to update, do so. + current_cycle++ + + //If there are tiles to update, do so. + tick_progress = "updating turf properties" + if(tiles_to_update.len) + updating_tiles = TRUE + for(var/turf/simulated/T in tiles_to_update) if(. && T && !T.update_air_properties()) - . = 0 //If a runtime occured, make sure we can sense it. - //message_admins("ZASALERT: Unable run turf/simualted/update_air_properties()") + //If a runtime occured, make sure we can sense it. + . = 0 + + updating_tiles = FALSE + if(.) - tiles_to_update = list() + if(tiles_to_update_alternate) + tiles_to_update = tiles_to_update_alternate + tiles_to_update_alternate = null + else + tiles_to_update = list() + + else if(tiles_to_update_alternate) + tiles_to_update |= tiles_to_update_alternate + tiles_to_update_alternate = null + + //Rebuild zones. + if(.) + tick_progress = "rebuilding zones" + if(zones_needing_rebuilt.len) + for(var/zone/zone in zones_needing_rebuilt) + zone.Rebuild() + + zones_needing_rebuilt = list() //Check sanity on connection objects. if(.) - tick_progress = "connections_to_check" + tick_progress = "checking/creating connections" if(connections_to_check.len) - for(var/connection/C in connections_to_check) - C.CheckPassSanity() - connections_to_check = list() + checking_connections = TRUE - //Ensure tiles still have zones. - if(.) - tick_progress = "tiles_to_reconsider_zones" - if(tiles_to_reconsider_zones.len) - for(var/turf/simulated/T in tiles_to_reconsider_zones) - if(!T.zone) - new /zone(T) - tiles_to_reconsider_zones = list() + for(var/connection/C in connections_to_check) + C.Cleanup() + + for(var/turf/simulated/turf_1 in potential_intrazone_connections) + for(var/turf/simulated/turf_2 in potential_intrazone_connections[turf_1]) + + if(!turf_1.zone || !turf_2.zone) + continue + + if(turf_1.zone == turf_2.zone) + continue + + var/should_skip = FALSE + if(turf_1 in air_master.turfs_with_connections) + + for(var/connection/C in turfs_with_connections[turf_1]) + if(C.B == turf_2 || C.A == turf_2) + should_skip = TRUE + break + if(should_skip) + continue + + new /connection(turf_1, turf_2) + + checking_connections = FALSE + + potential_intrazone_connections = list() + + if(connections_to_check_alternate) + connections_to_check = connections_to_check_alternate + connections_to_check_alternate = null + else + connections_to_check = list() //Process zones. if(.) - tick_progress = "zone/process()" - for(var/zone/Z in zones) + tick_progress = "processing zones" + for(var/zone/Z in active_zones) if(Z.last_update < current_cycle) var/output = Z.process() if(Z) Z.last_update = current_cycle if(. && Z && !output) . = 0 + + //Ensure tiles still have zones. + if(.) + tick_progress = "reconsidering zones on turfs" + if(tiles_to_reconsider_zones.len) + reconsidering_zones = TRUE + + for(var/turf/simulated/T in tiles_to_reconsider_zones) + if(!T.zone) + new /zone(T) + + reconsidering_zones = FALSE + + if(tiles_to_reconsider_alternate) + tiles_to_reconsider_zones = tiles_to_reconsider_alternate + tiles_to_reconsider_alternate = null + else + tiles_to_reconsider_zones = list() + //Process fires. if(.) - tick_progress = "active_hotspots (fire)" + tick_progress = "processing fire" for(var/obj/fire/F in active_hotspots) if(. && F && !F.process()) . = 0 if(.) - tick_progress = "success" \ No newline at end of file + tick_progress = "success" + + +/datum/controller/air_system/proc/AddTurfToUpdate(turf/simulated/outdated_turf) + var/list/tiles_to_check = list() + + if(istype(outdated_turf)) + tiles_to_check |= outdated_turf + + if(istype(outdated_turf, /turf)) + for(var/direction in cardinal) + var/turf/simulated/adjacent_turf = get_step(outdated_turf, direction) + if(istype(adjacent_turf)) + tiles_to_check |= adjacent_turf + + if(updating_tiles) + if(!tiles_to_update_alternate) + tiles_to_update_alternate = tiles_to_check + else + tiles_to_update_alternate |= tiles_to_check + else + tiles_to_update |= tiles_to_check + + +/datum/controller/air_system/proc/AddConnectionToCheck(connection/connection) + if(checking_connections) + if(istype(connection, /list)) + if(!connections_to_check_alternate) + connections_to_check_alternate = connection + + else if(!connections_to_check_alternate) + connections_to_check_alternate = list() + + connections_to_check_alternate |= connection + + else + connections_to_check |= connection + + +/datum/controller/air_system/proc/ReconsiderTileZone(var/turf/simulated/zoneless_turf) + if(zoneless_turf.zone) + return + + if(reconsidering_zones) + if(!tiles_to_reconsider_alternate) + tiles_to_reconsider_alternate = list() + + tiles_to_reconsider_alternate |= zoneless_turf + + else + tiles_to_reconsider_zones |= zoneless_turf + + +/datum/controller/air_system/proc/AddIntrazoneConnection(var/turf/simulated/A, var/turf/simulated/B) + if(!istype(A) || !istype(B)) + return + + if(A in potential_intrazone_connections) + if(B in potential_intrazone_connections[A]) + return + + if (B in potential_intrazone_connections) + if(A in potential_intrazone_connections[B]) + return + + potential_intrazone_connections[B] += A + + else + potential_intrazone_connections[B] = list(A) \ No newline at end of file diff --git a/code/ZAS/Fire.dm b/code/ZAS/Fire.dm index 6909ccd213d..a40746f52f6 100644 --- a/code/ZAS/Fire.dm +++ b/code/ZAS/Fire.dm @@ -38,9 +38,6 @@ turf/simulated/hotspot_expose(exposed_temperature, exposed_volume, soh) new /obj/fire(src,1000) - //active_hotspot.just_spawned = (current_cycle < air_master.current_cycle) - //remove just_spawned protection if no longer processing this cell - return igniting /obj/fire @@ -128,12 +125,12 @@ turf/simulated/hotspot_expose(exposed_temperature, exposed_volume, soh) //Spread the fire. if(!(locate(/obj/fire) in enemy_tile)) - if( prob( 50 + 50 * (firelevel/zas_settings.Get(/datum/ZAS_Setting/fire_firelevel_multiplier)) ) && S.CanPass(null, enemy_tile, 0,0) && enemy_tile.CanPass(null, S, 0,0)) + if( prob( 50 + 50 * (firelevel/vsc.fire_firelevel_multiplier) ) && S.CanPass(null, enemy_tile, 0,0) && enemy_tile.CanPass(null, S, 0,0)) new/obj/fire(enemy_tile,firelevel) //seperate part of the present gas //this is done to prevent the fire burning all gases in a single pass - var/datum/gas_mixture/flow = air_contents.remove_ratio(zas_settings.Get(/datum/ZAS_Setting/fire_consumption_rate)) + var/datum/gas_mixture/flow = air_contents.remove_ratio(vsc.fire_consuption_rate) ///////////////////////////////// FLOW HAS BEEN CREATED /// DONT DELETE THE FIRE UNTIL IT IS MERGED BACK OR YOU WILL DELETE AIR /////////////////////////////////////////////// if(flow) @@ -225,7 +222,7 @@ datum/gas_mixture/proc/zburn(obj/effect/decal/cleanable/liquid_fuel/liquid, forc var/total_reactants = total_fuel + total_oxygen //determine the amount of reactants actually reacting - var/used_reactants_ratio = min( max(total_reactants * firelevel / zas_settings.Get(/datum/ZAS_Setting/fire_firelevel_multiplier), 0.2), total_reactants) / total_reactants + var/used_reactants_ratio = min( max(total_reactants * firelevel / vsc.fire_firelevel_multiplier, 0.2), total_reactants) / total_reactants //remove and add gasses as calculated oxygen -= min(oxygen, total_oxygen * used_reactants_ratio ) @@ -246,7 +243,7 @@ datum/gas_mixture/proc/zburn(obj/effect/decal/cleanable/liquid_fuel/liquid, forc if(liquid.amount <= 0) del liquid //calculate the energy produced by the reaction and then set the new temperature of the mix - temperature = (starting_energy + zas_settings.Get(/datum/ZAS_Setting/fire_fuel_energy_release) * total_fuel) / heat_capacity() + temperature = (starting_energy + vsc.fire_fuel_energy_release * total_fuel) / heat_capacity() update_values() value = total_reactants * used_reactants_ratio @@ -256,34 +253,31 @@ datum/gas_mixture/proc/check_recombustability(obj/effect/decal/cleanable/liquid_ //this is a copy proc to continue a fire after its been started. var/datum/gas/volatile_fuel/fuel = locate() in trace_gases - var/value = 0 if(oxygen && (toxins || fuel || liquid)) if(liquid) - value = 1 - else if (toxins && !value) - value = 1 - else if(fuel && !value) - value = 1 + return 1 + if (toxins) + return 1 + if(fuel) + return 1 - return value + return 0 datum/gas_mixture/proc/check_combustability(obj/effect/decal/cleanable/liquid_fuel/liquid) //this check comes up very often and is thus centralized here to ease adding stuff var/datum/gas/volatile_fuel/fuel = locate() in trace_gases - var/value = 0 if(oxygen && (toxins || fuel || liquid)) if(liquid) - value = 1 - else if (toxins >= 0.7 && !value) - value = 1 - else if(fuel && !value) - if(fuel.moles >= 1.4) - value = 1 + return 1 + if (toxins >= 0.7) + return 1 + if(fuel && fuel.moles >= 1.4) + return 1 - return value + return 0 datum/gas_mixture/proc/calculate_firelevel(obj/effect/decal/cleanable/liquid_fuel/liquid) //Calculates the firelevel based on one equation instead of having to do this multiple times in different areas. @@ -309,31 +303,30 @@ datum/gas_mixture/proc/calculate_firelevel(obj/effect/decal/cleanable/liquid_fue //slows down the burning when the concentration of the reactants is low var/dampening_multiplier = total_combustables / (total_combustables + nitrogen + carbon_dioxide) //calculates how close the mixture of the reactants is to the optimum - var/mix_multiplier = 1 / (1 + (5 * ((oxygen / total_combustables) ^2))) + var/mix_multiplier = 1 / (1 + (5 * ((oxygen / total_combustables) ** 2))) //toss everything together - firelevel = zas_settings.Get(/datum/ZAS_Setting/fire_firelevel_multiplier) * mix_multiplier * dampening_multiplier + firelevel = vsc.fire_firelevel_multiplier * mix_multiplier * dampening_multiplier return max( 0, firelevel) -/mob/living/carbon/human/proc/FireBurn(var/firelevel, var/last_temperature, var/pressure) -// mostly using the old proc from Sky until I can think of something better +/mob/living/proc/FireBurn(var/firelevel, var/last_temperature, var/pressure) + var/mx = 5 * firelevel/vsc.fire_firelevel_multiplier * min(pressure / ONE_ATMOSPHERE, 1) + apply_damage(2.5*mx, BURN) + + +/mob/living/carbon/human/FireBurn(var/firelevel, var/last_temperature, var/pressure) //Burns mobs due to fire. Respects heat transfer coefficients on various body parts. //Due to TG reworking how fireprotection works, this is kinda less meaningful. - var - head_exposure = 1 - chest_exposure = 1 - groin_exposure = 1 - legs_exposure = 1 - arms_exposure = 1 - - //determine the multiplier - //minimize this for low-pressure enviroments - var/mx = 5 * firelevel/zas_settings.Get(/datum/ZAS_Setting/fire_firelevel_multiplier) * min(pressure / ONE_ATMOSPHERE, 1) + var/head_exposure = 1 + var/chest_exposure = 1 + var/groin_exposure = 1 + var/legs_exposure = 1 + var/arms_exposure = 1 //Get heat transfer coefficients for clothing. - //skytodo: kill anyone who breaks things then orders me to fix them + for(var/obj/item/clothing/C in src) if(l_hand == C || r_hand == C) continue @@ -349,6 +342,8 @@ datum/gas_mixture/proc/calculate_firelevel(obj/effect/decal/cleanable/liquid_fue legs_exposure = 0 if(C.body_parts_covered & ARMS) arms_exposure = 0 + //minimize this for low-pressure enviroments + var/mx = 5 * firelevel/vsc.fire_firelevel_multiplier * min(pressure / ONE_ATMOSPHERE, 1) //Always check these damage procs first if fire damage isn't working. They're probably what's wrong. @@ -359,5 +354,3 @@ datum/gas_mixture/proc/calculate_firelevel(obj/effect/decal/cleanable/liquid_fue apply_damage(0.6*mx*legs_exposure, BURN, "r_leg", 0, 0, "Fire") apply_damage(0.4*mx*arms_exposure, BURN, "l_arm", 0, 0, "Fire") apply_damage(0.4*mx*arms_exposure, BURN, "r_arm", 0, 0, "Fire") - - //flash_pain() diff --git a/code/ZAS/Functions.dm b/code/ZAS/Functions.dm index ce24513418e..3037e13f412 100644 --- a/code/ZAS/Functions.dm +++ b/code/ZAS/Functions.dm @@ -155,16 +155,17 @@ proc/ZConnect(turf/simulated/A,turf/simulated/B) //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.zone == B.zone) + air_master.AddIntrazoneConnection(A,B) + return - if(A.CanPass(null,B,0,1)) + if(A.CanPass(null, B, 1.5, 1) && A.zone.air.compare(B.zone.air)) 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)) + if(A in air_master.turfs_with_connections) + for(var/connection/C in air_master.turfs_with_connections[A]) + if(C.B == B || C.A == B) return //Make the connection. diff --git a/code/ZAS/Plasma.dm b/code/ZAS/Plasma.dm index 5936f3843b0..9f0e95f6617 100644 --- a/code/ZAS/Plasma.dm +++ b/code/ZAS/Plasma.dm @@ -1,5 +1,43 @@ var/image/contamination_overlay = image('icons/effects/contamination.dmi') +/pl_control + var/PLASMA_DMG = 3 + var/PLASMA_DMG_NAME = "Plasma Damage Amount" + var/PLASMA_DMG_DESC = "Self Descriptive" + + var/CLOTH_CONTAMINATION = 1 + var/CLOTH_CONTAMINATION_NAME = "Cloth Contamination" + var/CLOTH_CONTAMINATION_DESC = "If this is on, plasma does damage by getting into cloth." + + var/PLASMAGUARD_ONLY = 0 + var/PLASMAGUARD_ONLY_NAME = "\"PlasmaGuard Only\"" + var/PLASMAGUARD_ONLY_DESC = "If this is on, only biosuits and spacesuits protect against contamination and ill effects." + + var/GENETIC_CORRUPTION = 0 + var/GENETIC_CORRUPTION_NAME = "Genetic Corruption Chance" + var/GENETIC_CORRUPTION_DESC = "Chance of genetic corruption as well as toxic damage, X in 10,000." + + var/SKIN_BURNS = 0 + var/SKIN_BURNS_DESC = "Plasma has an effect similar to mustard gas on the un-suited." + var/SKIN_BURNS_NAME = "Skin Burns" + + var/EYE_BURNS = 1 + var/EYE_BURNS_NAME = "Eye Burns" + var/EYE_BURNS_DESC = "Plasma burns the eyes of anyone not wearing eye protection." + + var/CONTAMINATION_LOSS = 0.02 + var/CONTAMINATION_LOSS_NAME = "Contamination Loss" + var/CONTAMINATION_LOSS_DESC = "How much toxin damage is dealt from contaminated clothing" //Per tick? ASK ARYN + + var/PLASMA_HALLUCINATION = 0 + var/PLASMA_HALLUCINATION_NAME = "Plasma Hallucination" + var/PLASMA_HALLUCINATION_DESC = "Does being in plasma cause you to hallucinate?" + + var/N2O_HALLUCINATION = 1 + var/N2O_HALLUCINATION_NAME = "N2O Hallucination" + var/N2O_HALLUCINATION_DESC = "Does being in sleeping gas cause you to hallucinate?" + + obj/var/contaminated = 0 @@ -40,21 +78,21 @@ obj/var/contaminated = 0 //Handles all the bad things plasma can do. //Contamination - if(zas_settings.Get(/datum/ZAS_Setting/CLOTH_CONTAMINATION)) contaminate() + if(vsc.plc.CLOTH_CONTAMINATION) contaminate() //Anything else requires them to not be dead. if(stat >= 2) return //Burn skin if exposed. - if(zas_settings.Get(/datum/ZAS_Setting/SKIN_BURNS)) + if(vsc.plc.SKIN_BURNS) if(!pl_head_protected() || !pl_suit_protected()) burn_skin(0.75) if(prob(20)) src << "\red Your skin burns!" updatehealth() //Burn eyes if exposed. - if(zas_settings.Get(/datum/ZAS_Setting/EYE_BURNS)) + if(vsc.plc.EYE_BURNS) if(!head) if(!wear_mask) burn_eyes() @@ -70,8 +108,8 @@ obj/var/contaminated = 0 burn_eyes() //Genetic Corruption - if(zas_settings.Get(/datum/ZAS_Setting/GENETIC_CORRUPTION)) - if(rand(1,10000) < zas_settings.Get(/datum/ZAS_Setting/GENETIC_CORRUPTION)) + if(vsc.plc.GENETIC_CORRUPTION) + if(rand(1,10000) < vsc.plc.GENETIC_CORRUPTION) randmutb(src) src << "\red High levels of toxins cause you to spontaneously mutate." domutcheck(src,null) @@ -90,7 +128,7 @@ obj/var/contaminated = 0 /mob/living/carbon/human/proc/pl_head_protected() //Checks if the head is adequately sealed. if(head) - if(zas_settings.Get(/datum/ZAS_Setting/PLASMAGUARD_ONLY)) + if(vsc.plc.PLASMAGUARD_ONLY) if(head.flags & PLASMAGUARD) return 1 else if(head.flags & HEADCOVERSEYES) @@ -100,7 +138,7 @@ obj/var/contaminated = 0 /mob/living/carbon/human/proc/pl_suit_protected() //Checks if the suit is adequately sealed. if(wear_suit) - if(zas_settings.Get(/datum/ZAS_Setting/PLASMAGUARD_ONLY)) + if(vsc.plc.PLASMAGUARD_ONLY) if(wear_suit.flags & PLASMAGUARD) return 1 else if(wear_suit.flags_inv & HIDEJUMPSUIT) return 1 @@ -116,7 +154,7 @@ obj/var/contaminated = 0 turf/Entered(obj/item/I) . = ..() //Items that are in plasma, but not on a mob, can still be contaminated. - if(istype(I) && zas_settings.Get(/datum/ZAS_Setting/CLOTH_CONTAMINATION)) + if(istype(I) && vsc.plc.CLOTH_CONTAMINATION) var/datum/gas_mixture/env = return_air(1) if(!env) return diff --git a/code/ZAS/Variable Settings.dm b/code/ZAS/Variable Settings.dm index 09501ffc78a..5dd951fe52e 100644 --- a/code/ZAS/Variable Settings.dm +++ b/code/ZAS/Variable Settings.dm @@ -1,75 +1,71 @@ var/global/vs_control/vsc = new -// Whoever made this fucking thing: I hate you so much. -vs_control/var - // N3X15 - Added back in so we can tweak performance. - airflow_push = 0 - airflow_push_NAME="Airflow - Push shit around" - airflow_push_DESC="1=yes please rape my server, 0=no" - airflow_push_METHOD="Toggle" // See ChangeSettings(). I'd rather not let people break this. +/vs_control + var/fire_consuption_rate = 0.25 + var/fire_consuption_rate_NAME = "Fire - Air Consumption Ratio" + var/fire_consuption_rate_DESC = "Ratio of air removed and combusted per tick." - fire_consuption_rate = 0.75 - fire_consuption_rate_NAME = "Fire - Air Consumption Ratio" - fire_consuption_rate_DESC = "Ratio of air removed and combusted per tick." + var/fire_firelevel_multiplier = 25 + var/fire_firelevel_multiplier_NAME = "Fire - Firelevel Constant" + var/fire_firelevel_multiplier_DESC = "Multiplied by the equation for firelevel, affects mainly the extingiushing of fires." - fire_firelevel_multiplier = 25 - fire_firelevel_multiplier_NAME = "Fire - Firelevel Constant" - fire_firelevel_multiplier_DESC = "Multiplied by the equation for firelevel, affects mainly the extingiushing of fires." - - fire_fuel_energy_release = 550000 - fire_fuel_energy_release_NAME = "Fire - Fuel energy release" - fire_fuel_energy_release_DESC = "The energy in joule released when burning one mol of a burnable substance" + var/fire_fuel_energy_release = 397000 + var/fire_fuel_energy_release_NAME = "Fire - Fuel energy release" + var/fire_fuel_energy_release_DESC = "The energy in joule released when burning one mol of a burnable substance" - airflow_lightest_pressure = 20 - airflow_lightest_pressure_NAME = "Airflow - Small Movement Threshold %" - airflow_lightest_pressure_DESC = "Percent of 1 Atm. at which items with the small weight classes will move." + var/IgnitionLevel = 0.5 + var/IgnitionLevel_DESC = "Determines point at which fire can ignite" - airflow_light_pressure = 35 - airflow_light_pressure_NAME = "Airflow - Medium Movement Threshold %" - airflow_light_pressure_DESC = "Percent of 1 Atm. at which items with the medium weight classes will move." + var/airflow_lightest_pressure = 20 + var/airflow_lightest_pressure_NAME = "Airflow - Small Movement Threshold %" + var/airflow_lightest_pressure_DESC = "Percent of 1 Atm. at which items with the small weight classes will move." - airflow_medium_pressure = 50 - airflow_medium_pressure_NAME = "Airflow - Heavy Movement Threshold %" - airflow_medium_pressure_DESC = "Percent of 1 Atm. at which items with the largest weight classes will move." + var/airflow_light_pressure = 35 + var/airflow_light_pressure_NAME = "Airflow - Medium Movement Threshold %" + var/airflow_light_pressure_DESC = "Percent of 1 Atm. at which items with the medium weight classes will move." - airflow_heavy_pressure = 65 - airflow_heavy_pressure_NAME = "Airflow - Mob Movement Threshold %" - airflow_heavy_pressure_DESC = "Percent of 1 Atm. at which mobs will move." + var/airflow_medium_pressure = 50 + var/airflow_medium_pressure_NAME = "Airflow - Heavy Movement Threshold %" + var/airflow_medium_pressure_DESC = "Percent of 1 Atm. at which items with the largest weight classes will move." - airflow_dense_pressure = 85 - airflow_dense_pressure_NAME = "Airflow - Dense Movement Threshold %" - airflow_dense_pressure_DESC = "Percent of 1 Atm. at which items with canisters and closets will move." + var/airflow_heavy_pressure = 65 + var/airflow_heavy_pressure_NAME = "Airflow - Mob Movement Threshold %" + var/airflow_heavy_pressure_DESC = "Percent of 1 Atm. at which mobs will move." - airflow_stun_pressure = 60 - airflow_stun_pressure_NAME = "Airflow - Mob Stunning Threshold %" - airflow_stun_pressure_DESC = "Percent of 1 Atm. at which mobs will be stunned by airflow." + var/airflow_dense_pressure = 85 + var/airflow_dense_pressure_NAME = "Airflow - Dense Movement Threshold %" + var/airflow_dense_pressure_DESC = "Percent of 1 Atm. at which items with canisters and closets will move." - airflow_stun_cooldown = 60 - airflow_stun_cooldown_NAME = "Aiflow Stunning - Cooldown" - airflow_stun_cooldown_DESC = "How long, in tenths of a second, to wait before stunning them again." + var/airflow_stun_pressure = 60 + var/airflow_stun_pressure_NAME = "Airflow - Mob Stunning Threshold %" + var/airflow_stun_pressure_DESC = "Percent of 1 Atm. at which mobs will be stunned by airflow." - airflow_stun = 1 - airflow_stun_NAME = "Airflow Impact - Stunning" - airflow_stun_DESC = "How much a mob is stunned when hit by an object." + var/airflow_stun_cooldown = 60 + var/airflow_stun_cooldown_NAME = "Aiflow Stunning - Cooldown" + var/airflow_stun_cooldown_DESC = "How long, in tenths of a second, to wait before stunning them again." - airflow_damage = 2 - airflow_damage_NAME = "Airflow Impact - Damage" - airflow_damage_DESC = "Damage from airflow impacts." + var/airflow_stun = 1 + var/airflow_stun_NAME = "Airflow Impact - Stunning" + var/airflow_stun_DESC = "How much a mob is stunned when hit by an object." - airflow_speed_decay = 1.5 - airflow_speed_decay_NAME = "Airflow Speed Decay" - airflow_speed_decay_DESC = "How rapidly the speed gained from airflow decays." + var/airflow_damage = 2 + var/airflow_damage_NAME = "Airflow Impact - Damage" + var/airflow_damage_DESC = "Damage from airflow impacts." - airflow_delay = 30 - airflow_delay_NAME = "Airflow Retrigger Delay" - airflow_delay_DESC = "Time in deciseconds before things can be moved by airflow again." + var/airflow_speed_decay = 1.5 + var/airflow_speed_decay_NAME = "Airflow Speed Decay" + var/airflow_speed_decay_DESC = "How rapidly the speed gained from airflow decays." - airflow_mob_slowdown = 1 - airflow_mob_slowdown_NAME = "Airflow Slowdown" - airflow_mob_slowdown_DESC = "Time in tenths of a second to add as a delay to each movement by a mob if they are fighting the pull of the airflow." + var/airflow_delay = 30 + var/airflow_delay_NAME = "Airflow Retrigger Delay" + var/airflow_delay_DESC = "Time in deciseconds before things can be moved by airflow again." - var/connection_insulation = 0.4 + var/airflow_mob_slowdown = 1 + var/airflow_mob_slowdown_NAME = "Airflow Slowdown" + var/airflow_mob_slowdown_DESC = "Time in tenths of a second to add as a delay to each movement by a mob if they are fighting the pull of the airflow." + + var/connection_insulation = 1 var/connection_insulation_NAME = "Connections - Insulation" var/connection_insulation_DESC = "How insulative a connection is, in terms of heat transfer. 1 is perfectly insulative, and 0 is perfectly conductive." @@ -77,264 +73,263 @@ vs_control/var var/connection_temperature_delta_NAME = "Connections - Temperature Difference" var/connection_temperature_delta_DESC = "The smallest temperature difference which will cause heat to travel through doors." -vs_control - var - list/settings = list() - list/bitflags = list("1","2","4","8","16","32","64","128","256","512","1024") // Oh jesus why. Learn to shift bits, you idiots. - pl_control/plc = new() - New() - . = ..() - settings = vars.Copy() +/vs_control/var/list/settings = list() +/vs_control/var/list/bitflags = list("1","2","4","8","16","32","64","128","256","512","1024") +/vs_control/var/pl_control/plc = new() - var/datum/D = new() //Ensure only unique vars are put through by making a datum and removing all common vars. - for(var/V in D.vars) +/vs_control/New() + . = ..() + settings = vars.Copy() + + var/datum/D = new() //Ensure only unique vars are put through by making a datum and removing all common vars. + for(var/V in D.vars) + settings -= V + + for(var/V in settings) + if(findtextEx(V,"_RANDOM") || findtextEx(V,"_DESC") || findtextEx(V,"_METHOD")) settings -= V - for(var/V in settings) - if(findtextEx(V,"_RANDOM") || findtextEx(V,"_DESC") || findtextEx(V,"_METHOD")) - settings -= V + settings -= "settings" + settings -= "bitflags" + settings -= "plc" - settings -= "settings" - settings -= "bitflags" - settings -= "plc" - - proc/ChangeSettingsDialog(mob/user,list/L) - //var/which = input(user,"Choose a setting:") in L - var/dat = "" - for(var/ch in L) - if(findtextEx(ch,"_RANDOM") || findtextEx(ch,"_DESC") || findtextEx(ch,"_METHOD") || findtextEx(ch,"_NAME")) continue - var/vw - var/vw_desc = "No Description." - var/vw_name = ch - if(ch in plc.settings) - vw = plc.vars[ch] - if("[ch]_DESC" in plc.vars) vw_desc = plc.vars["[ch]_DESC"] - if("[ch]_NAME" in plc.vars) vw_name = plc.vars["[ch]_NAME"] - else - vw = vars[ch] - if("[ch]_DESC" in vars) vw_desc = vars["[ch]_DESC"] - if("[ch]_NAME" in vars) vw_name = vars["[ch]_NAME"] - dat += "[vw_name] = [vw] \[Change\]
" - dat += "[vw_desc]

" - user << browse(dat,"window=settings") - Topic(href,href_list) - if("changevar" in href_list) - ChangeSetting(usr,href_list["changevar"]) - proc/ChangeSetting(mob/user,ch) +/vs_control/proc/ChangeSettingsDialog(mob/user,list/L) + //var/which = input(user,"Choose a setting:") in L + var/dat = "" + for(var/ch in L) + if(findtextEx(ch,"_RANDOM") || findtextEx(ch,"_DESC") || findtextEx(ch,"_METHOD") || findtextEx(ch,"_NAME")) continue var/vw - var/how = "Text" - var/display_description = ch + var/vw_desc = "No Description." + var/vw_name = ch if(ch in plc.settings) vw = plc.vars[ch] - if("[ch]_NAME" in plc.vars) - display_description = plc.vars["[ch]_NAME"] - if("[ch]_METHOD" in plc.vars) - how = plc.vars["[ch]_METHOD"] - else - if(isnum(vw)) - how = "Numeric" - else - how = "Text" + if("[ch]_DESC" in plc.vars) vw_desc = plc.vars["[ch]_DESC"] + if("[ch]_NAME" in plc.vars) vw_name = plc.vars["[ch]_NAME"] else vw = vars[ch] - if("[ch]_NAME" in vars) - display_description = vars["[ch]_NAME"] - if("[ch]_METHOD" in vars) - how = vars["[ch]_METHOD"] + if("[ch]_DESC" in vars) vw_desc = vars["[ch]_DESC"] + if("[ch]_NAME" in vars) vw_name = vars["[ch]_NAME"] + dat += "[vw_name] = [vw] \[Change\]
" + dat += "[vw_desc]

" + user << browse(dat,"window=settings") + +/vs_control/Topic(href,href_list) + if("changevar" in href_list) + ChangeSetting(usr,href_list["changevar"]) + +/vs_control/proc/ChangeSetting(mob/user,ch) + var/vw + var/how = "Text" + var/display_description = ch + if(ch in plc.settings) + vw = plc.vars[ch] + if("[ch]_NAME" in plc.vars) + display_description = plc.vars["[ch]_NAME"] + if("[ch]_METHOD" in plc.vars) + how = plc.vars["[ch]_METHOD"] + else + if(isnum(vw)) + how = "Numeric" else - if(isnum(vw)) - how = "Numeric" - else - how = "Text" - var/newvar = vw - switch(how) - if("Numeric") - newvar = input(user,"Enter a number:","Settings",newvar) as num - if("Bit Flag") - var/flag = input(user,"Toggle which bit?","Settings") in bitflags - flag = text2num(flag) - if(newvar & flag) - newvar &= ~flag - else - newvar |= flag - if("Toggle") - newvar = !newvar - if("Text") - newvar = input(user,"Enter a string:","Settings",newvar) as text - if("Long Text") - newvar = input(user,"Enter text:","Settings",newvar) as message - vw = newvar - if(ch in plc.settings) - plc.vars[ch] = vw + how = "Text" + else + vw = vars[ch] + if("[ch]_NAME" in vars) + display_description = vars["[ch]_NAME"] + if("[ch]_METHOD" in vars) + how = vars["[ch]_METHOD"] else - vars[ch] = vw - if(how == "Toggle") - newvar = (newvar?"ON":"OFF") - world << "\blue [key_name(user)] changed the setting [display_description] to [newvar]." - if(ch in plc.settings) - ChangeSettingsDialog(user,plc.settings) - else - ChangeSettingsDialog(user,settings) - proc/RandomizeWithProbability() - for(var/V in settings) - var/newvalue - if("[V]_RANDOM" in vars) - if(isnum(vars["[V]_RANDOM"])) - newvalue = prob(vars["[V]_RANDOM"]) - else if(istext(vars["[V]_RANDOM"])) - newvalue = roll(vars["[V]_RANDOM"]) - else - newvalue = vars[V] - V = newvalue + if(isnum(vw)) + how = "Numeric" + else + how = "Text" + var/newvar = vw + switch(how) + if("Numeric") + newvar = input(user,"Enter a number:","Settings",newvar) as num + if("Bit Flag") + var/flag = input(user,"Toggle which bit?","Settings") in bitflags + flag = text2num(flag) + if(newvar & flag) + newvar &= ~flag + else + newvar |= flag + if("Toggle") + newvar = !newvar + if("Text") + newvar = input(user,"Enter a string:","Settings",newvar) as text + if("Long Text") + newvar = input(user,"Enter text:","Settings",newvar) as message + vw = newvar + if(ch in plc.settings) + plc.vars[ch] = vw + else + vars[ch] = vw + if(how == "Toggle") + newvar = (newvar?"ON":"OFF") + world << "\blue [key_name(user)] changed the setting [display_description] to [newvar]." + if(ch in plc.settings) + ChangeSettingsDialog(user,plc.settings) + else + ChangeSettingsDialog(user,settings) - proc/ChangePlasma() - for(var/V in plc.settings) - plc.Randomize(V) - - proc/SetDefault(var/mob/user) - var/list/setting_choices = list("Plasma - Standard", "Plasma - Low Hazard", "Plasma - High Hazard", "Plasma - Oh Shit!",\ - "ZAS - Normal", "ZAS - Forgiving", "ZAS - Dangerous", "ZAS - Hellish") - var/def = input(user, "Which of these presets should be used?") as null|anything in setting_choices - if(!def) - return - switch(def) - if("Plasma - Standard") - plc.CLOTH_CONTAMINATION = 1 //If this is on, plasma does damage by getting into cloth. - plc.PLASMAGUARD_ONLY = 0 - plc.GENETIC_CORRUPTION = 0 //Chance of genetic corruption as well as toxic damage, X in 1000. - plc.SKIN_BURNS = 0 //Plasma has an effect similar to mustard gas on the un-suited. - plc.EYE_BURNS = 1 //Plasma burns the eyes of anyone not wearing eye protection. - plc.PLASMA_HALLUCINATION = 0 - plc.CONTAMINATION_LOSS = 0.02 - - if("Plasma - Low Hazard") - plc.CLOTH_CONTAMINATION = 0 //If this is on, plasma does damage by getting into cloth. - plc.PLASMAGUARD_ONLY = 0 - plc.GENETIC_CORRUPTION = 0 //Chance of genetic corruption as well as toxic damage, X in 1000 - plc.SKIN_BURNS = 0 //Plasma has an effect similar to mustard gas on the un-suited. - plc.EYE_BURNS = 1 //Plasma burns the eyes of anyone not wearing eye protection. - plc.PLASMA_HALLUCINATION = 0 - plc.CONTAMINATION_LOSS = 0.01 - - if("Plasma - High Hazard") - plc.CLOTH_CONTAMINATION = 1 //If this is on, plasma does damage by getting into cloth. - plc.PLASMAGUARD_ONLY = 0 - plc.GENETIC_CORRUPTION = 0 //Chance of genetic corruption as well as toxic damage, X in 1000. - plc.SKIN_BURNS = 1 //Plasma has an effect similar to mustard gas on the un-suited. - plc.EYE_BURNS = 1 //Plasma burns the eyes of anyone not wearing eye protection. - plc.PLASMA_HALLUCINATION = 1 - plc.CONTAMINATION_LOSS = 0.05 - - if("Plasma - Oh Shit!") - plc.CLOTH_CONTAMINATION = 1 //If this is on, plasma does damage by getting into cloth. - plc.PLASMAGUARD_ONLY = 1 - plc.GENETIC_CORRUPTION = 5 //Chance of genetic corruption as well as toxic damage, X in 1000. - plc.SKIN_BURNS = 1 //Plasma has an effect similar to mustard gas on the un-suited. - plc.EYE_BURNS = 1 //Plasma burns the eyes of anyone not wearing eye protection. - plc.PLASMA_HALLUCINATION = 1 - plc.CONTAMINATION_LOSS = 0.075 - - if("ZAS - Normal") - airflow_push=0 - airflow_lightest_pressure = 20 - airflow_light_pressure = 35 - airflow_medium_pressure = 50 - airflow_heavy_pressure = 65 - airflow_dense_pressure = 85 - airflow_stun_pressure = 60 - airflow_stun_cooldown = 60 - airflow_stun = 1 - airflow_damage = 2 - airflow_speed_decay = 1.5 - airflow_delay = 30 - airflow_mob_slowdown = 1 - - if("ZAS - Forgiving") - airflow_push=0 - airflow_lightest_pressure = 45 - airflow_light_pressure = 60 - airflow_medium_pressure = 120 - airflow_heavy_pressure = 110 - airflow_dense_pressure = 200 - airflow_stun_pressure = 150 - airflow_stun_cooldown = 90 - airflow_stun = 0.15 - airflow_damage = 0.15 - airflow_speed_decay = 1.5 - airflow_delay = 50 - airflow_mob_slowdown = 0 - - if("ZAS - Dangerous") - airflow_push=1 - airflow_lightest_pressure = 15 - airflow_light_pressure = 30 - airflow_medium_pressure = 45 - airflow_heavy_pressure = 55 - airflow_dense_pressure = 70 - airflow_stun_pressure = 50 - airflow_stun_cooldown = 50 - airflow_stun = 2 - airflow_damage = 3 - airflow_speed_decay = 1.2 - airflow_delay = 25 - airflow_mob_slowdown = 2 - - if("ZAS - Hellish") - airflow_push=1 - airflow_lightest_pressure = 20 - airflow_light_pressure = 30 - airflow_medium_pressure = 40 - airflow_heavy_pressure = 50 - airflow_dense_pressure = 60 - airflow_stun_pressure = 40 - airflow_stun_cooldown = 40 - airflow_stun = 3 - airflow_damage = 4 - airflow_speed_decay = 1 - airflow_delay = 20 - airflow_mob_slowdown = 3 - - - world << "\blue [key_name(user)] changed the global plasma/ZAS settings to \"[def]\"" - -pl_control - var/list/settings = list() - New() - . = ..() - settings = vars.Copy() - - var/datum/D = new() //Ensure only unique vars are put through by making a datum and removing all common vars. - for(var/V in D.vars) - settings -= V - - for(var/V in settings) - if(findtextEx(V,"_RANDOM") || findtextEx(V,"_DESC")) - settings -= V - - settings -= "settings" - proc/Randomize(V) +/vs_control/proc/RandomizeWithProbability() + for(var/V in settings) var/newvalue if("[V]_RANDOM" in vars) if(isnum(vars["[V]_RANDOM"])) newvalue = prob(vars["[V]_RANDOM"]) else if(istext(vars["[V]_RANDOM"])) - var/txt = vars["[V]_RANDOM"] - if(findtextEx(txt,"PROB")) - txt = text2list(txt,"/") - txt[1] = replacetext(txt[1],"PROB","") - var/p = text2num(txt[1]) - var/r = txt[2] - if(prob(p)) - newvalue = roll(r) - else - newvalue = vars[V] - else if(findtextEx(txt,"PICK")) - txt = replacetext(txt,"PICK","") - txt = text2list(txt,",") - newvalue = pick(txt) - else - newvalue = roll(txt) + newvalue = roll(vars["[V]_RANDOM"]) else newvalue = vars[V] - vars[V] = newvalue + V = newvalue + +/vs_control/proc/ChangePlasma() + for(var/V in plc.settings) + plc.Randomize(V) + +/vs_control/proc/SetDefault(var/mob/user) + var/list/setting_choices = list("Plasma - Standard", "Plasma - Low Hazard", "Plasma - High Hazard", "Plasma - Oh Shit!",\ + "ZAS - Normal", "ZAS - Forgiving", "ZAS - Dangerous", "ZAS - Hellish") + var/def = input(user, "Which of these presets should be used?") as null|anything in setting_choices + if(!def) + return + switch(def) + if("Plasma - Standard") + plc.CLOTH_CONTAMINATION = 1 //If this is on, plasma does damage by getting into cloth. + plc.PLASMAGUARD_ONLY = 0 + plc.GENETIC_CORRUPTION = 0 //Chance of genetic corruption as well as toxic damage, X in 1000. + plc.SKIN_BURNS = 0 //Plasma has an effect similar to mustard gas on the un-suited. + plc.EYE_BURNS = 1 //Plasma burns the eyes of anyone not wearing eye protection. + plc.PLASMA_HALLUCINATION = 0 + plc.CONTAMINATION_LOSS = 0.02 + + if("Plasma - Low Hazard") + plc.CLOTH_CONTAMINATION = 0 //If this is on, plasma does damage by getting into cloth. + plc.PLASMAGUARD_ONLY = 0 + plc.GENETIC_CORRUPTION = 0 //Chance of genetic corruption as well as toxic damage, X in 1000 + plc.SKIN_BURNS = 0 //Plasma has an effect similar to mustard gas on the un-suited. + plc.EYE_BURNS = 1 //Plasma burns the eyes of anyone not wearing eye protection. + plc.PLASMA_HALLUCINATION = 0 + plc.CONTAMINATION_LOSS = 0.01 + + if("Plasma - High Hazard") + plc.CLOTH_CONTAMINATION = 1 //If this is on, plasma does damage by getting into cloth. + plc.PLASMAGUARD_ONLY = 0 + plc.GENETIC_CORRUPTION = 0 //Chance of genetic corruption as well as toxic damage, X in 1000. + plc.SKIN_BURNS = 1 //Plasma has an effect similar to mustard gas on the un-suited. + plc.EYE_BURNS = 1 //Plasma burns the eyes of anyone not wearing eye protection. + plc.PLASMA_HALLUCINATION = 1 + plc.CONTAMINATION_LOSS = 0.05 + + if("Plasma - Oh Shit!") + plc.CLOTH_CONTAMINATION = 1 //If this is on, plasma does damage by getting into cloth. + plc.PLASMAGUARD_ONLY = 1 + plc.GENETIC_CORRUPTION = 5 //Chance of genetic corruption as well as toxic damage, X in 1000. + plc.SKIN_BURNS = 1 //Plasma has an effect similar to mustard gas on the un-suited. + plc.EYE_BURNS = 1 //Plasma burns the eyes of anyone not wearing eye protection. + plc.PLASMA_HALLUCINATION = 1 + plc.CONTAMINATION_LOSS = 0.075 + + if("ZAS - Normal") + airflow_lightest_pressure = 20 + airflow_light_pressure = 35 + airflow_medium_pressure = 50 + airflow_heavy_pressure = 65 + airflow_dense_pressure = 85 + airflow_stun_pressure = 60 + airflow_stun_cooldown = 60 + airflow_stun = 1 + airflow_damage = 2 + airflow_speed_decay = 1.5 + airflow_delay = 30 + airflow_mob_slowdown = 1 + + if("ZAS - Forgiving") + airflow_lightest_pressure = 45 + airflow_light_pressure = 60 + airflow_medium_pressure = 120 + airflow_heavy_pressure = 110 + airflow_dense_pressure = 200 + airflow_stun_pressure = 150 + airflow_stun_cooldown = 90 + airflow_stun = 0.15 + airflow_damage = 0.15 + airflow_speed_decay = 1.5 + airflow_delay = 50 + airflow_mob_slowdown = 0 + + if("ZAS - Dangerous") + airflow_lightest_pressure = 15 + airflow_light_pressure = 30 + airflow_medium_pressure = 45 + airflow_heavy_pressure = 55 + airflow_dense_pressure = 70 + airflow_stun_pressure = 50 + airflow_stun_cooldown = 50 + airflow_stun = 2 + airflow_damage = 3 + airflow_speed_decay = 1.2 + airflow_delay = 25 + airflow_mob_slowdown = 2 + + if("ZAS - Hellish") + airflow_lightest_pressure = 20 + airflow_light_pressure = 30 + airflow_medium_pressure = 40 + airflow_heavy_pressure = 50 + airflow_dense_pressure = 60 + airflow_stun_pressure = 40 + airflow_stun_cooldown = 40 + airflow_stun = 3 + airflow_damage = 4 + airflow_speed_decay = 1 + airflow_delay = 20 + airflow_mob_slowdown = 3 + + + world << "\blue [key_name(user)] changed the global plasma/ZAS settings to \"[def]\"" + +/pl_control/var/list/settings = list() + +/pl_control/New() + . = ..() + settings = vars.Copy() + + var/datum/D = new() //Ensure only unique vars are put through by making a datum and removing all common vars. + for(var/V in D.vars) + settings -= V + + for(var/V in settings) + if(findtextEx(V,"_RANDOM") || findtextEx(V,"_DESC")) + settings -= V + + settings -= "settings" + +/pl_control/proc/Randomize(V) + var/newvalue + if("[V]_RANDOM" in vars) + if(isnum(vars["[V]_RANDOM"])) + newvalue = prob(vars["[V]_RANDOM"]) + else if(istext(vars["[V]_RANDOM"])) + var/txt = vars["[V]_RANDOM"] + if(findtextEx(txt,"PROB")) + txt = text2list(txt,"/") + txt[1] = replacetext(txt[1],"PROB","") + var/p = text2num(txt[1]) + var/r = txt[2] + if(prob(p)) + newvalue = roll(r) + else + newvalue = vars[V] + else if(findtextEx(txt,"PICK")) + txt = replacetext(txt,"PICK","") + txt = text2list(txt,",") + newvalue = pick(txt) + else + newvalue = roll(txt) + else + newvalue = vars[V] + vars[V] = newvalue diff --git a/code/ZAS/ZAS_Turfs.dm b/code/ZAS/ZAS_Turfs.dm index e7f5f4402f8..12ac2df2445 100644 --- a/code/ZAS/ZAS_Turfs.dm +++ b/code/ZAS/ZAS_Turfs.dm @@ -20,15 +20,6 @@ return GM -// For new turfs -/turf/proc/copy_air_from(var/turf/T) - oxygen = T.oxygen - carbon_dioxide = T.carbon_dioxide - nitrogen = T.nitrogen - toxins = T.toxins - - temperature = T.temperature - /turf/remove_air(amount as num) var/datum/gas_mixture/GM = new @@ -45,11 +36,16 @@ return GM /turf/simulated/var/current_graphic = null + /turf/simulated/var/tmp/datum/gas_mixture/air + /turf/simulated/var/tmp/processing = 1 + /turf/simulated/var/tmp/air_check_directions = 0 //Do not modify this, just add turf to air_master.tiles_to_update + +/turf/simulated/var/tmp/unsim_check_directions = 0 //See above. + /turf/simulated/var/tmp/obj/fire/active_hotspot -/turf/simulated/var/tmp/was_icy=0 /turf/simulated/proc/update_visuals() overlays = null @@ -57,47 +53,12 @@ var/siding_icon_state = return_siding_icon_state() if(siding_icon_state) overlays += image('icons/turf/floors.dmi',siding_icon_state) - - // ONLY USED IF ZAS_SETTINGS SAYS SO. var/datum/gas_mixture/model = return_air() - if(model.graphics & GRAPHICS_COLD) - if(!was_icy) - wet=3 // Custom ice - was_icy=1 - var/o="" - //if(is_plating()) - // o="snowfloor_s" - //else - if(is_plasteel_floor()) - o="snowfloor" - if(o!="") - overlays += image('icons/turf/overlays.dmi',o) - else - if(was_icy) - wet=0 - was_icy=0 - if(prob(10)) - wet = 1 - if(wet_overlay) - overlays -= wet_overlay - wet_overlay = null - wet_overlay = image('icons/effects/water.dmi',src,"wet_floor") - overlays += wet_overlay - - spawn(800) - if (!istype(src)) return - if(wet >= 2) return - wet = 0 - if(wet_overlay) - overlays -= wet_overlay - wet_overlay = null - if(model.graphics & GRAPHICS_PLASMA) - overlays.Add(plmaster) - if(model.graphics & GRAPHICS_N2O) - overlays.Add(slmaster) - //if(model.graphics & GRAPHICS_REAGENTS) - // overlays.Add(slmaster/*rlmaster*/) - + switch(model.graphic) + if(1) + overlays.Add(plmaster) //TODO: Make invisible plasma an option + if(2) + overlays.Add(slmaster) /turf/simulated/New() ..() @@ -133,16 +94,10 @@ air_master.tiles_to_update.Add(tile) ..() -/turf/simulated/copy_air_from(var/turf/T) - //if(istype(T,/turf/simulated)) - // var/turf/simulated/ST=T - // air=ST.air - air=T.return_air() - /turf/simulated/assume_air(datum/gas_mixture/giver) if(!giver) return 0 if(zone) - zone.air.merge(giver) + zone.assume_air(giver) return 1 else return ..() @@ -158,11 +113,8 @@ /turf/simulated/remove_air(amount as num) if(zone) - var/datum/gas_mixture/removed = null - removed = zone.air.remove(amount) - if(zone.air.check_tile_graphic()) - update_visuals(zone.air) - return removed + return zone.remove_air(amount) + else if(air) var/datum/gas_mixture/removed = null removed = air.remove(amount) @@ -178,14 +130,21 @@ var/air_directions_archived = air_check_directions air_check_directions = 0 + var/unsim_directions_archived = unsim_check_directions + unsim_check_directions = 0 + for(var/direction in cardinal) - if(ZAirPass(get_step(src,direction))) - air_check_directions |= direction + var/turf/check_turf = get_step(src, direction) + if(ZAirPass(check_turf)) + if(istype(check_turf, /turf/simulated)) + air_check_directions |= direction + else if(istype(check_turf, /turf/space) || istype(check_turf, /turf/unsimulated)) + unsim_check_directions |= direction if(!zone && !blocks_air) //No zone, but not a wall. for(var/direction in DoorDirections) //Check door directions first. - if(air_check_directions&direction) - var/turf/simulated/T = get_step(src,direction) + if(air_check_directions & direction) + var/turf/simulated/T = get_step(src, direction) if(!istype(T)) continue if(T.zone) @@ -193,7 +152,7 @@ break if(!zone) //Still no zone for(var/direction in CounterDoorDirections) //Check the others second. - if(air_check_directions&direction) + if(air_check_directions & direction) var/turf/simulated/T = get_step(src,direction) if(!istype(T)) continue @@ -206,84 +165,31 @@ new/zone(list(src)) //Check pass sanity of the connections. - if("\ref[src]" in air_master.turfs_with_connections) - for(var/connection/C in air_master.turfs_with_connections["\ref[src]"]) - air_master.connections_to_check |= C + if(src in air_master.turfs_with_connections) + air_master.AddConnectionToCheck(air_master.turfs_with_connections[src]) + + if(zone && CanPass(null, src, 0, 0)) - if(zone && !zone.rebuild) - if(zone.air.check_tile_graphic()) - update_visuals(zone.air) for(var/direction in cardinal) var/turf/T = get_step(src,direction) if(!istype(T)) continue - //I can connect to air in this direction - if(air_check_directions&direction) - - //If either block air, we must look to see if the adjacent turfs need rebuilt. - if(!CanPass(null, T, 0, 0)) - - //Target blocks air - if(!T.CanPass(null, T, 0, 0)) - var/turf/NT = get_step(T, direction) - - //If that turf is in my zone still, rebuild. - if(istype(NT,/turf/simulated) && NT in zone.contents) - zone.rebuild = 1 - - //If that is an unsimulated tile in my zone, see if we need to rebuild or just remove. - else if(istype(NT) && NT in zone.unsimulated_tiles) - var/consider_rebuild = 0 - for(var/d in cardinal) - var/turf/UT = get_step(NT,d) - if(istype(UT, /turf/simulated) && UT.zone == zone && UT.CanPass(null, NT, 0, 0)) //If we find a neighboring tile that is in the same zone, check if we need to rebuild - consider_rebuild = 1 - break - if(consider_rebuild) - zone.rebuild = 1 //Gotta check if we need to rebuild, dammit - else - zone.RemoveTurf(NT) //Not adjacent to anything, and unsimulated. Goodbye~ - - //To make a closed connection through closed door. - ZConnect(T, src) - - //If I block air. - else if(T.zone && !T.zone.rebuild) - var/turf/NT = get_step(src, reverse_direction(direction)) - - //If I am splitting a zone, rebuild. - if(istype(NT,/turf/simulated) && (NT in T.zone.contents || (NT.zone && T in NT.zone.contents))) - T.zone.rebuild = 1 - - //If NT is unsimulated, parse if I should remove it or rebuild. - else if(istype(NT) && NT in T.zone.unsimulated_tiles) - var/consider_rebuild = 0 - for(var/d in cardinal) - var/turf/UT = get_step(NT,d) - if(istype(UT, /turf/simulated) && UT.zone == T.zone && UT.CanPass(null, NT, 0, 0)) //If we find a neighboring tile that is in the same zone, check if we need to rebuild - consider_rebuild = 1 - break - - //Needs rebuilt. - if(consider_rebuild) - T.zone.rebuild = 1 - - //Not adjacent to anything, and unsimulated. Goodbye~ - else - T.zone.RemoveTurf(NT) - - else - //Produce connection through open door. - ZConnect(src,T) + //I can connect to air or space in this direction + if((air_check_directions & direction && !(air_directions_archived & direction)) || \ + (unsim_check_directions & direction && !(unsim_directions_archived & direction))) + ZConnect(src,T) + zone.ActivateIfNeeded() + if(T.zone) T.zone.ActivateIfNeeded() //Something like a wall was built, changing the geometry. - else if(air_directions_archived&direction) + else if((!(air_check_directions & direction) && air_directions_archived & direction) || \ + (!(unsim_check_directions & direction) && unsim_directions_archived & direction)) var/turf/NT = get_step(T, direction) //If the tile is in our own zone, and we cannot connect to it, better rebuild. if(istype(NT,/turf/simulated) && NT in zone.contents) - zone.rebuild = 1 + air_master.zones_needing_rebuilt.Add(zone) //Parse if we need to remove the tile, or rebuild the zone. else if(istype(NT) && NT in zone.unsimulated_tiles) @@ -301,7 +207,7 @@ //The unsimulated turf is adjacent to another one of our zone's turfs, // better rebuild to be sure we didn't get cut in twain if(consider_rebuild) - zone.rebuild = 1 + air_master.zones_needing_rebuilt.Add(zone) //Not adjacent to anything, and unsimulated. Goodbye~ else @@ -340,13 +246,13 @@ return 0 for(var/obj/obstacle in src) - if(istype(obstacle, /obj/machinery/door) && !obstacle:air_properties_vary_with_direction) + if(istype(obstacle, /obj/machinery/door) && !(obstacle:air_properties_vary_with_direction)) continue if(!obstacle.CanPass(null, T, 1.5, 1)) return 0 for(var/obj/obstacle in T) - if(istype(obstacle, /obj/machinery/door) && !obstacle:air_properties_vary_with_direction) + if(istype(obstacle, /obj/machinery/door) && !(obstacle:air_properties_vary_with_direction)) continue if(!obstacle.CanPass(null, src, 1.5, 1)) return 0 @@ -362,13 +268,13 @@ return 0 for(var/obj/obstacle in src) - if(istype(obstacle, /obj/machinery/door) && !obstacle:air_properties_vary_with_direction) + if(istype(obstacle, /obj/machinery/door) && !(obstacle:air_properties_vary_with_direction)) continue if(!obstacle.CanPass(null, T, 0, 0)) return 0 for(var/obj/obstacle in T) - if(istype(obstacle, /obj/machinery/door) && !obstacle:air_properties_vary_with_direction) + if(istype(obstacle, /obj/machinery/door) && !(obstacle:air_properties_vary_with_direction)) continue if(!obstacle.CanPass(null, src, 0, 0)) return 0 diff --git a/code/ZAS/ZAS_Zones.dm b/code/ZAS/ZAS_Zones.dm index c538a6c7c2a..cd77fbbbf21 100644 --- a/code/ZAS/ZAS_Zones.dm +++ b/code/ZAS/ZAS_Zones.dm @@ -1,18 +1,30 @@ -var/list/zones = list() var/list/DoorDirections = list(NORTH,WEST) //Which directions doors turfs can connect to zones var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs can connect to zones /zone var/dbg_output = 0 //Enables debug output. - var/rebuild = 0 //If 1, zone will be rebuilt on next process. Not sure if used. + var/datum/gas_mixture/air //The air contents of the zone. + var/datum/gas_mixture/archived_air + var/list/contents //All the tiles that are contained in this zone. - var/list/connections // /connection objects which refer to connections with other zones, e.g. through a door. - var/list/connected_zones //Parallels connections, but lists zones to which this one is connected and the number - //of points they're connected at. - var/list/closed_connection_zones //Same as connected_zones, but for zones where the door or whatever is closed. var/list/unsimulated_tiles // Any space tiles in this list will cause air to flow out. + + var/datum/gas_mixture/air_unsim //Overall average of the air in connected unsimualted tiles. + var/unsim_air_needs_update = 0 //Set to 1 on geometry changes, marks air_unsim as needing update. + + var/list/connections //connection objects which refer to connections with other zones, e.g. through a door. + var/list/direct_connections //connections which directly connect two zones. + + var/list/connected_zones //Parallels connections, but lists zones to which this one is connected and the number + //of points they're connected at. + var/list/closed_connection_zones //Same as connected_zones, but for zones where the door or whatever is closed. + var/last_update = 0 + var/last_rebuilt = 0 + var/status = ZONE_ACTIVE + var/interactions_with_neighbors = 0 + var/interactions_with_unsim = 0 var/progress = "nothing" @@ -46,34 +58,42 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs air.update_values() //Add this zone to the global list. - zones.Add(src) + if(air_master) + air_master.zones.Add(src) + air_master.active_zones.Add(src) - //LEGACY, DO NOT USE. Use the SoftDelete proc. +//DO NOT USE. Use the SoftDelete proc. /zone/Del() //Ensuring the zone list doesn't get clogged with null values. for(var/turf/simulated/T in contents) RemoveTurf(T) - air_master.tiles_to_reconsider_zones += T + air_master.ReconsiderTileZone(T) for(var/zone/Z in connected_zones) if(src in Z.connected_zones) Z.connected_zones.Remove(src) - for(var/connection/C in connections) - air_master.connections_to_check += C - zones.Remove(src) + air_master.AddConnectionToCheck(connections) + + if(air_master) + air_master.zones.Remove(src) + air_master.active_zones.Remove(src) + air_master.zones_needing_rebuilt.Remove(src) air = null . = ..() - //Handles deletion via garbage collection. +//Handles deletion via garbage collection. /zone/proc/SoftDelete() - zones.Remove(src) + if(air_master) + air_master.zones.Remove(src) + air_master.active_zones.Remove(src) + air_master.zones_needing_rebuilt.Remove(src) air = null //Ensuring the zone list doesn't get clogged with null values. for(var/turf/simulated/T in contents) RemoveTurf(T) - air_master.tiles_to_reconsider_zones += T + air_master.ReconsiderTileZone(T) //Removing zone connections and scheduling connection cleanup for(var/zone/Z in connected_zones) @@ -81,8 +101,7 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs Z.connected_zones.Remove(src) connected_zones = null - for(var/connection/C in connections) - air_master.connections_to_check += C + air_master.AddConnectionToCheck(connections) connections = null return 1 @@ -99,7 +118,9 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs contents += T if(air) air.group_multiplier++ + T.zone = src + else if(!unsimulated_tiles) unsimulated_tiles = list() @@ -108,6 +129,8 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs unsimulated_tiles += T contents -= T + unsim_air_needs_update = 1 + /zone/proc/RemoveTurf(turf/T) //Same, but in reverse. if(istype(T, /turf/simulated)) @@ -116,13 +139,60 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs contents -= T if(air) air.group_multiplier-- + if(T.zone == src) T.zone = null + + if(!contents.len) + SoftDelete() + else if(unsimulated_tiles) unsimulated_tiles -= T if(!unsimulated_tiles.len) unsimulated_tiles = null + unsim_air_needs_update = 1 + +//Updates the air_unsim var +/zone/proc/UpdateUnsimAvg() + if(!unsimulated_tiles || !unsimulated_tiles.len) //if we don't have any unsimulated tiles, we can't do much. + return + + if(!unsim_air_needs_update && air_unsim) //if air_unsim doesn't exist, we need to create it even if we don't need an update. + return + + unsim_air_needs_update = 0 + + if(!air_unsim) + air_unsim = new /datum/gas_mixture + + air_unsim.oxygen = 0 + air_unsim.nitrogen = 0 + air_unsim.carbon_dioxide = 0 + air_unsim.toxins = 0 + air_unsim.temperature = 0 + + var/correction_ratio = max(1, max(max(1, air.group_multiplier) + 3, 1) + unsimulated_tiles.len) / unsimulated_tiles.len + + for(var/turf/T in unsimulated_tiles) + if(!istype(T, /turf/simulated)) + air_unsim.oxygen += T.oxygen + air_unsim.carbon_dioxide += T.carbon_dioxide + air_unsim.nitrogen += T.nitrogen + air_unsim.toxins += T.toxins + air_unsim.temperature += T.temperature/unsimulated_tiles.len + + //These values require adjustment in order to properly represent a room of the specified size. + air_unsim.oxygen *= correction_ratio + air_unsim.carbon_dioxide *= correction_ratio + air_unsim.nitrogen *= correction_ratio + air_unsim.toxins *= correction_ratio + + air_unsim.group_multiplier = unsimulated_tiles.len + + air_unsim.update_values() + return + ////////////// //PROCESSING// ////////////// @@ -140,11 +210,6 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs progress = "problem with: Rebuild()" - //Does rebuilding stuff. - if(rebuild) - rebuild = 0 - Rebuild() //Shoving this into a proc. - if(!contents.len) //If we got soft deleted. return @@ -162,15 +227,22 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs progress = "problem with: ShareSpace()" + if(unsim_air_needs_update) + unsim_air_needs_update = 0 + UpdateUnsimAvg() + if(unsimulated_tiles) if(locate(/turf/simulated) in unsimulated_tiles) for(var/turf/simulated/T in unsimulated_tiles) unsimulated_tiles -= T if(unsimulated_tiles.len) - var/moved_air = ShareSpace(air,unsimulated_tiles) + var/moved_air = ShareSpace(air, air_unsim) - if(moved_air > zas_settings.Get(/datum/ZAS_Setting/airflow_lightest_pressure)) + if(!air.compare(air_unsim)) + interactions_with_unsim++ + + if(moved_air > vsc.airflow_lightest_pressure) AirflowSpace(src) else unsimulated_tiles = null @@ -178,28 +250,24 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs //Check the graphic. progress = "problem with: modifying turf graphics" - air.graphics = 0 + air.graphic = 0 if(air.toxins > MOLES_PLASMA_VISIBLE) - air.graphics |= GRAPHICS_PLASMA - if(air.trace_gases.len) + air.graphic = 1 + else if(air.trace_gases.len) var/datum/gas/sleeping_agent = locate(/datum/gas/sleeping_agent) in air.trace_gases if(sleeping_agent && (sleeping_agent.moles > 1)) - air.graphics |= GRAPHICS_N2O - // If configured and cold, maek ice - if(zas_settings.Get(/datum/ZAS_Setting/ice_formation)) - if(air.temperature <= TEMPERATURE_ICE_FORMATION && air.return_pressure()>MIN_PRESSURE_ICE_FORMATION) - air.graphics |= GRAPHICS_COLD + air.graphic = 2 progress = "problem with an inbuilt byond function: some conditional checks" //Only run through the individual turfs if there's reason to. - if(air.graphics != air.graphics_archived || air.temperature > PLASMA_FLASHPOINT) + if(air.graphic != air.graphic_archived || air.temperature > PLASMA_FLASHPOINT) progress = "problem with: turf/simulated/update_visuals()" for(var/turf/simulated/S in contents) //Update overlays. - if(air.graphics != air.graphics_archived) + if(air.graphic != air.graphic_archived) if(S.HasDoor(1)) S.update_visuals() else @@ -216,7 +284,7 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs progress = "problem with: calculating air graphic" //Archive graphic so we can know if it's different. - air.graphics_archived = air.graphics + air.graphic_archived = air.graphic progress = "problem with: calculating air temp" @@ -230,17 +298,13 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs progress = "problem with: ZMerge(), a couple of misc procs" - for(var/connection/C in connections) - //Check if the connection is valid first. - if(!C.Cleanup()) - continue + if(length(direct_connections)) + for(var/connection/C in direct_connections) - //Do merging if conditions are met. Specifically, if there's a non-door connection - //to somewhere with space, the zones are merged regardless of equilibrium, to speed - //up spacing in areas with double-plated windows. - if(C && C.A.zone && C.B.zone) - //indirect = 2 is a direct connection. - if( C.indirect == 2 ) + //Do merging if conditions are met. Specifically, if there's a non-door connection + //to somewhere with space, the zones are merged regardless of equilibrium, to speed + //up spacing in areas with double-plated windows. + if(C.A.zone && C.B.zone) if(C.A.zone.air.compare(C.B.zone.air) || unsimulated_tiles) ZMerge(C.A.zone,C.B.zone) @@ -252,11 +316,18 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs if(Z.last_update > last_update) continue + //Handle adjacent zones that are sleeping + if(Z.status == ZONE_SLEEPING) + if(air.compare(Z.air)) + continue + + else + Z.SetStatus(ZONE_ACTIVE) + if(air && Z.air) //Ensure we're not doing pointless calculations on equilibrium zones. - var/moles_delta = abs(air.total_moles() - Z.air.total_moles()) - if(moles_delta > 0.1 || abs(air.temperature - Z.air.temperature) > 0.1) - if(abs(Z.air.return_pressure() - air.return_pressure()) > zas_settings.Get(/datum/ZAS_Setting/airflow_lightest_pressure)) + if(!air.compare(Z.air)) + if(abs(Z.air.return_pressure() - air.return_pressure()) > vsc.airflow_lightest_pressure) Airflow(src,Z) var/unsimulated_boost = 0 if(unsimulated_tiles) @@ -266,16 +337,116 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs unsimulated_boost = max(0, min(3, unsimulated_boost)) ShareRatio( air , Z.air , connected_zones[Z] + unsimulated_boost) + Z.interactions_with_neighbors++ + interactions_with_neighbors++ + for(var/zone/Z in closed_connection_zones) //If that zone has already processed, skip it. if(Z.last_update > last_update) continue + + var/handle_temperature = abs(air.temperature - Z.air.temperature) > vsc.connection_temperature_delta + + if(Z.status == ZONE_SLEEPING) + if (handle_temperature) + Z.SetStatus(ZONE_ACTIVE) + else + continue + if(air && Z.air) - if( abs(air.temperature - Z.air.temperature) > zas_settings.Get(/datum/ZAS_Setting/connection_temperature_delta) ) + if( handle_temperature ) ShareHeat(air, Z.air, closed_connection_zones[Z]) + Z.interactions_with_neighbors++ + interactions_with_neighbors++ + + if(!interactions_with_neighbors && !interactions_with_unsim) + SetStatus(ZONE_SLEEPING) + + interactions_with_neighbors = 0 + interactions_with_unsim = 0 + progress = "all components completed successfully, the problem is not here" + +/zone/proc/SetStatus(var/new_status) + if(status == ZONE_SLEEPING && new_status == ZONE_ACTIVE) + air_master.active_zones.Add(src) + status = ZONE_ACTIVE + + else if(status == ZONE_ACTIVE && new_status == ZONE_SLEEPING) + air_master.active_zones.Remove(src) + status = ZONE_SLEEPING + + if(unsimulated_tiles && unsimulated_tiles.len) + UpdateUnsimAvg() + air.copy_from(air_unsim) + + if(!archived_air) + archived_air = new + archived_air.copy_from(air) + + +/zone/proc/CheckStatus() + return status + + +/zone/proc/ActivateIfNeeded() + if(status == ZONE_ACTIVE) return + + var/difference = 0 + + if(unsimulated_tiles && unsimulated_tiles.len) + UpdateUnsimAvg() + if(!air.compare(air_unsim)) + difference = 1 + + if(!difference) + for(var/zone/Z in connected_zones) //Check adjacent zones for air difference. + if(!air.compare(Z.air)) + difference = 1 + break + + if(difference) //We have a difference, activate the zone. + SetStatus(ZONE_ACTIVE) + + return + + +/zone/proc/assume_air(var/datum/gas_mixture/giver) + if(status == ZONE_ACTIVE) + return air.merge(giver) + + else + if(unsimulated_tiles && unsimulated_tiles.len) + UpdateUnsimAvg() + var/datum/gas_mixture/compare_air = new + compare_air.copy_from(giver) + compare_air.add(air_unsim) + compare_air.divide(air.group_multiplier) + + if(air_unsim.compare(compare_air)) + return 0 + + var/result = air.merge(giver) + + if(!archived_air.compare(air)) + SetStatus(ZONE_ACTIVE) + return result + + +/zone/proc/remove_air(var/amount) + if(status == ZONE_ACTIVE) + return air.remove(amount) + + else + var/result = air.remove(amount) + + if(!archived_air.compare(air)) + SetStatus(ZONE_ACTIVE) + + return result + //////////////// //Air Movement// //////////////// @@ -337,6 +508,7 @@ proc/ShareRatio(datum/gas_mixture/A, datum/gas_mixture/B, connecting_tiles) if(H) var/G_avg = (G.moles*size + H.moles*share_size) / (size+share_size) G.moles = (G.moles - G_avg) * (1-ratio) + G_avg + H.moles = (H.moles - G_avg) * (1-ratio) + G_avg else H = new G.type @@ -345,6 +517,15 @@ proc/ShareRatio(datum/gas_mixture/A, datum/gas_mixture/B, connecting_tiles) G.moles = (G.moles - G_avg) * (1-ratio) + G_avg H.moles = (H.moles - G_avg) * (1-ratio) + G_avg + for(var/datum/gas/G in B.trace_gases) + var/datum/gas/H = locate(G.type) in A.trace_gases + if(!H) + H = new G.type + A.trace_gases += H + var/G_avg = (G.moles*size) / (size+share_size) + G.moles = (G.moles - G_avg) * (1-ratio) + G_avg + H.moles = (H.moles - G_avg) * (1-ratio) + G_avg + A.update_values() B.update_values() @@ -353,7 +534,7 @@ proc/ShareRatio(datum/gas_mixture/A, datum/gas_mixture/B, connecting_tiles) proc/ShareSpace(datum/gas_mixture/A, list/unsimulated_tiles, dbg_output) //A modified version of ShareRatio for spacing gas at the same rate as if it were going into a large airless room. - if(!unsimulated_tiles || !unsimulated_tiles.len) + if(!unsimulated_tiles) return 0 var @@ -366,6 +547,22 @@ proc/ShareSpace(datum/gas_mixture/A, list/unsimulated_tiles, dbg_output) size = max(1,A.group_multiplier) + var/tileslen + var/share_size + + if(istype(unsimulated_tiles, /datum/gas_mixture)) + var/datum/gas_mixture/avg_unsim = unsimulated_tiles + unsim_oxygen = avg_unsim.oxygen + unsim_co2 = avg_unsim.carbon_dioxide + unsim_nitrogen = avg_unsim.nitrogen + unsim_plasma = avg_unsim.toxins + unsim_temperature = avg_unsim.temperature + share_size = max(1, max(size + 3, 1) + avg_unsim.group_multiplier) + tileslen = avg_unsim.group_multiplier + + else if(istype(unsimulated_tiles, /list)) + if(!unsimulated_tiles.len) + return 0 // We use the same size for the potentially single space tile // as we use for the entire room. Why is this? // Short answer: We do not want larger rooms to depressurize more @@ -373,21 +570,26 @@ proc/ShareSpace(datum/gas_mixture/A, list/unsimulated_tiles, dbg_output) // oh-shit effect when large rooms get breached, but still having small // rooms remain pressurized for long enough to make escape possible. share_size = max(1, max(size + 3, 1) + unsimulated_tiles.len) - correction_ratio = share_size / unsimulated_tiles.len + var/correction_ratio = share_size / unsimulated_tiles.len - for(var/turf/T in unsimulated_tiles) - unsim_oxygen += T.oxygen - unsim_co2 += T.carbon_dioxide - unsim_nitrogen += T.nitrogen - unsim_plasma += T.toxins - unsim_temperature += T.temperature/unsimulated_tiles.len + for(var/turf/T in unsimulated_tiles) + unsim_oxygen += T.oxygen + unsim_co2 += T.carbon_dioxide + unsim_nitrogen += T.nitrogen + unsim_plasma += T.toxins + unsim_temperature += T.temperature/unsimulated_tiles.len - //These values require adjustment in order to properly represent a room of the specified size. - unsim_oxygen *= correction_ratio - unsim_co2 *= correction_ratio - unsim_nitrogen *= correction_ratio - unsim_plasma *= correction_ratio - unsim_heat_capacity = HEAT_CAPACITY_CALCULATION(unsim_oxygen,unsim_co2,unsim_nitrogen,unsim_plasma) + //These values require adjustment in order to properly represent a room of the specified size. + unsim_oxygen *= correction_ratio + unsim_co2 *= correction_ratio + unsim_nitrogen *= correction_ratio + unsim_plasma *= correction_ratio + tileslen = unsimulated_tiles.len + + else //invalid input type + return 0 + + unsim_heat_capacity = HEAT_CAPACITY_CALCULATION(unsim_oxygen, unsim_co2, unsim_nitrogen, unsim_plasma) var ratio = sharing_lookup_table[6] @@ -406,20 +608,20 @@ proc/ShareSpace(datum/gas_mixture/A, list/unsimulated_tiles, dbg_output) co2_avg = (full_co2 + unsim_co2) / (size + share_size) plasma_avg = (full_plasma + unsim_plasma) / (size + share_size) + temp_avg = 0 + + if((full_heat_capacity + unsim_heat_capacity) > 0) temp_avg = (A.temperature * full_heat_capacity + unsim_temperature * unsim_heat_capacity) / (full_heat_capacity + unsim_heat_capacity) - if(sharing_lookup_table.len >= unsimulated_tiles.len) //6 or more interconnecting tiles will max at 42% of air moved per tick. - ratio = sharing_lookup_table[unsimulated_tiles.len] + if(sharing_lookup_table.len >= tileslen) //6 or more interconnecting tiles will max at 42% of air moved per tick. + ratio = sharing_lookup_table[tileslen] A.oxygen = max(0, (A.oxygen - oxy_avg) * (1 - ratio) + oxy_avg ) A.nitrogen = max(0, (A.nitrogen - nit_avg) * (1 - ratio) + nit_avg ) A.carbon_dioxide = max(0, (A.carbon_dioxide - co2_avg) * (1 - ratio) + co2_avg ) A.toxins = max(0, (A.toxins - plasma_avg) * (1 - ratio) + plasma_avg ) - // EXPERIMENTAL: Disable space being cold - // N3X: Made this togglable for Pomf. Comment recovered from older code. - if(!zas_settings.Get(/datum/ZAS_Setting/space_isnt_cold)) - A.temperature = max(TCMB, (A.temperature - temp_avg) * (1 - ratio) + temp_avg ) + A.temperature = max(TCMB, (A.temperature - temp_avg) * (1 - ratio) + temp_avg ) for(var/datum/gas/G in A.trace_gases) var/G_avg = (G.moles * size) / (size + share_size) @@ -449,7 +651,7 @@ proc/ShareHeat(datum/gas_mixture/A, datum/gas_mixture/B, connecting_tiles) //WOOT WOOT TOUCH THIS AND YOU ARE A RETARD //We need to adjust it to account for the insulation settings. - ratio *= 1 - zas_settings.Get(/datum/ZAS_Setting/connection_insulation) + ratio *= 1 - vsc.connection_insulation A.temperature = max(0, (A.temperature - temp_avg) * (1- (ratio / max(1,A.group_multiplier)) ) + temp_avg ) B.temperature = max(0, (B.temperature - temp_avg) * (1- (ratio / max(1,B.group_multiplier)) ) + temp_avg ) @@ -458,72 +660,151 @@ proc/ShareHeat(datum/gas_mixture/A, datum/gas_mixture/B, connecting_tiles) /////////////////// //Zone Rebuilding// /////////////////// +//Used for updating zone geometry when a zone is cut into two parts. zone/proc/Rebuild() + if(last_rebuilt == air_master.current_cycle) + return + + last_rebuilt = air_master.current_cycle + + var/list/new_zone_contents = IsolateContents() + if(new_zone_contents.len == 1) + return + + var/list/current_contents + var/list/new_zones = list() + + contents = new_zone_contents[1] + air.group_multiplier = contents.len + + for(var/identifier in 2 to new_zone_contents.len) + current_contents = new_zone_contents[identifier] + var/zone/new_zone = new (current_contents) + new_zone.air.copy_from(air) + new_zones += new_zone + + for(var/connection/connection in connections) + connection.Cleanup() + + var/turf/simulated/adjacent + + for(var/turf/unsimulated in unsimulated_tiles) + for(var/direction in cardinal) + adjacent = get_step(unsimulated, direction) + + if(istype(adjacent) && adjacent.CanPass(null, unsimulated, 0, 0)) + for(var/zone/zone in new_zones) + if(adjacent in zone) + zone.AddTurf(unsimulated) + + +//Implements a two-pass connected component labeling algorithm to determine if the zone is, in fact, split. + +/zone/proc/IsolateContents() + var/list/current_adjacents = list() + var/adjacent_id + var/lowest_id + + var/list/identical_ids = list() + var/list/turfs = contents.Copy() + var/current_identifier = 1 + + for(var/turf/simulated/current in turfs) + lowest_id = null + current_adjacents = list() + + for(var/direction in cardinal) + if( !(current.air_check_directions & direction)) + continue + var/turf/simulated/adjacent = get_step(current, direction) + if(adjacent in turfs) + current_adjacents += adjacent + adjacent_id = turfs[adjacent] + + if(adjacent_id && (!lowest_id || adjacent_id < lowest_id)) + lowest_id = adjacent_id + + if(!lowest_id) + lowest_id = current_identifier++ + identical_ids += lowest_id + + for(var/turf/simulated/adjacent in current_adjacents) + adjacent_id = turfs[adjacent] + if(adjacent_id != lowest_id) + if(adjacent_id) + identical_ids[adjacent_id] = lowest_id + turfs[adjacent] = lowest_id + turfs[current] = lowest_id + + var/list/final_arrangement = list() + + for(var/turf/simulated/current in turfs) + current_identifier = identical_ids[turfs[current]] + + if( current_identifier > final_arrangement.len ) + final_arrangement.len = current_identifier + final_arrangement[current_identifier] = list(current) + + else + final_arrangement[current_identifier] += current + + //lazy but fast + final_arrangement.Remove(null) + + return final_arrangement + + +/* + if(!RequiresRebuild()) + return + //Choose a random turf and regenerate the zone from it. - var - turf/simulated/sample = locate() in contents - list/new_contents - problem = 0 + var/list/new_contents + var/list/new_unsimulated - // - var/list/turfs_to_consider = contents.Copy() + var/list/turfs_needing_zones = list() - while(!sample || !sample.CanPass(null, sample, 1.5, 1)) - if(sample) - turfs_to_consider.Remove(sample) - sample = locate() in turfs_to_consider - if(!sample) - break + var/list/zones_to_check_connections = list(src) - if(!istype(sample) || !sample.CanPass(null, sample, 1.5, 1)) //Not a single valid turf. - for(var/turf/simulated/T in contents) - air_master.tiles_to_update |= T + if(!locate(/turf/simulated/floor) in contents) + for(var/turf/simulated/turf in contents) + air_master.ReconsiderTileZone(turf) return SoftDelete() - new_contents = FloodFill(sample) + var/turfs_to_ignore = list() + if(direct_connections) + for(var/connection/connection in direct_connections) + if(connection.A.zone != src) + turfs_to_ignore += A + else if(connection.B.zone != src) + turfs_to_ignore += B - var/list/new_unsimulated = ( unsimulated_tiles ? unsimulated_tiles : list() ) + new_unsimulated = ( unsimulated_tiles ? unsimulated_tiles : list() ) + //Now, we have allocated the new turfs into proper lists, and we can start actually rebuilding. + + //If something isn't carried over, it will need a new zone. + for(var/turf/T in contents) + if(!(T in new_contents)) + RemoveTurf(T) + turfs_needing_zones += T + + //Handle addition of new turfs for(var/turf/S in new_contents) if(!istype(S, /turf/simulated)) new_unsimulated |= S new_contents.Remove(S) - if(contents.len != new_contents.len) - problem = 1 + //If something new is added, we need to deal with it seperately. + else if(!(S in contents) && istype(S, /turf/simulated)) + if(!(S.zone in zones_to_check_connections)) + zones_to_check_connections += S.zone - //If something isn't carried over, there was a complication. - for(var/turf/T in contents) - if(!(T in new_contents)) - T.zone = null - problem = 1 + S.zone.RemoveTurf(S) + AddTurf(S) - if(problem) - //Build some new zones for stuff that wasn't included. - var/list/turf/simulated/rebuild_turfs = contents - new_contents - var/list/turf/simulated/reconsider_turfs = list() - contents = new_contents - for(var/turf/simulated/T in rebuild_turfs) - if(!T.zone && T.CanPass(null, T, 1.5, 1)) - var/zone/Z = new /zone(T) - Z.air.copy_from(air) - else - reconsider_turfs |= T - for(var/turf/simulated/T in reconsider_turfs) - if(!T.zone && T.CanPass(null, T, 1.5, 1)) - var/zone/Z = new /zone(T) - Z.air.copy_from(air) - else if(!T in air_master.tiles_to_update) - air_master.tiles_to_update.Add(T) - - for(var/turf/simulated/T in contents) - if(T.zone && T.zone != src) - T.zone.RemoveTurf(T) - T.zone = src - else if(!T.zone) - T.zone = src - air.group_multiplier = contents.len + //Handle the addition of new unsimulated tiles. unsimulated_tiles = null if(new_unsimulated.len) @@ -535,20 +816,13 @@ zone/proc/Rebuild() if(istype(T) && T.zone && S.CanPass(null, T, 0, 0)) T.zone.AddTurf(S) -//UNUSED -/* -zone/proc/connected_zones() - //A legacy proc for getting connected zones. - . = list() - for(var/connection/C in connections) - var/zone/Z - if(C.A.zone == src) - Z = C.B.zone - else - Z = C.A.zone + //Finally, handle the orphaned turfs + + for(var/turf/simulated/T in turfs_needing_zones) + if(!T.zone) + zones_to_check_connections += new /zone(T) + + for(var/zone/zone in zones_to_check_connections) + for(var/connection/C in zone.connections) + C.Cleanup()*/ - if(Z in .) - .[Z]++ - else - . += Z - .[Z] = 1*/ diff --git a/code/controllers/master_controller.dm b/code/controllers/master_controller.dm index 78baecdd28a..658f2d7a217 100644 --- a/code/controllers/master_controller.dm +++ b/code/controllers/master_controller.dm @@ -58,7 +58,8 @@ datum/controller/game_controller/proc/setup() if(!air_master) air_master = new /datum/controller/air_system() - air_master.setup() +// air_master.setup() + air_master.Setup() if(!ticker) ticker = new /datum/controller/gameticker() @@ -128,8 +129,9 @@ datum/controller/game_controller/proc/process() timer = world.timeofday last_thing_processed = air_master.type - air_master.current_cycle++ - if(!air_master.tick()) //Runtimed. +/* air_master.current_cycle++ + if(!air_master.tick()) Runtimed.*/ + if(!air_master.Tick()) air_master.failed_ticks++ if(air_master.failed_ticks > 5) world << "RUNTIMES IN ATMOS TICKER. Killing air simulation!" diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index 771d79b60ec..a7295736afa 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -93,8 +93,8 @@ /obj/machinery/door/proc/bumpopen(mob/user as mob) if(operating) return - //if(user.last_airflow > world.time - vsc.airflow_delay) //Fakkit - if(user.last_airflow > world.time - zas_settings.Get("airflow_delay")) //Fakkit + if(user.last_airflow > world.time - vsc.airflow_delay) //Fakkit +// if(user.last_airflow > world.time - zas_settings.Get("airflow_delay")) //Fakkit return src.add_fingerprint(user) if(!src.requiresID()) diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 1a87f36ac00..6f89da4ec78 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -573,7 +573,7 @@ var/list/admin_verbs_mod = list( for (var/mob/V in hearers(mob.control_object)) V.show_message("[mob.control_object.name] says: \"" + msg + "\"", 2) feedback_add_details("admin_verb","OT") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - +/* /client/proc/kill_air() // -- TLE set category = "Debug" set name = "Kill Air" @@ -587,6 +587,21 @@ var/list/admin_verbs_mod = list( feedback_add_details("admin_verb","KA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! log_admin("[key_name(usr)] used 'kill air'.") message_admins("\blue [key_name_admin(usr)] used 'kill air'.", 1) +*/ + +/client/proc/kill_air() // -- TLE + set category = "Debug" + set name = "Kill Air" + set desc = "Toggle Air Processing" + if(air_processing_killed) + air_processing_killed = 0 + usr << "Enabled air processing." + else + air_processing_killed = 1 + usr << "Disabled air processing." + feedback_add_details("admin_verb","KA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + log_admin("[key_name(usr)] used 'kill air'.") + message_admins("\blue [key_name_admin(usr)] used 'kill air'.", 1) /client/proc/deadmin_self() set name = "De-admin self" diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 0a8d5a0744e..35d6dd0250c 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -2526,13 +2526,13 @@ else if(href_list["vsc"]) if(check_rights(R_ADMIN|R_SERVER)) if(href_list["vsc"] == "airflow") -/* vsc.ChangeSettingsDialog(usr,vsc.settings) + vsc.ChangeSettingsDialog(usr,vsc.settings) if(href_list["vsc"] == "plasma") - vsc.ChangeSettingsDialog(usr,vsc.plc.settings) */ - zas_settings.ChangeSettingsDialog(usr,zas_settings.settings) + vsc.ChangeSettingsDialog(usr,vsc.plc.settings) +// zas_settings.ChangeSettingsDialog(usr,zas_settings.settings) if(href_list["vsc"] == "default") - //vsc.SetDefault(usr) - zas_settings.SetDefault(usr) + vsc.SetDefault(usr) +// zas_settings.SetDefault(usr) // player info stuff if(href_list["add_player_info"]) diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index db38edf07d9..79e6bcb68bc 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -876,8 +876,8 @@ var/total_plasmaloss = 0 for(var/obj/item/I in src) if(I.contaminated) - //total_plasmaloss += vsc.plc.CONTAMINATION_LOSS - total_plasmaloss += zas_settings.Get("CONTAMINATION_LOSS") + total_plasmaloss += vsc.plc.CONTAMINATION_LOSS +// total_plasmaloss += zas_settings.Get("CONTAMINATION_LOSS") if(status_flags & GODMODE) return 0 //godmode adjustToxLoss(total_plasmaloss) diff --git a/code/setup.dm b/code/setup.dm index b7dfdad86ac..189042a3611 100644 --- a/code/setup.dm +++ b/code/setup.dm @@ -764,3 +764,7 @@ var/list/RESTRICTED_CAMERA_NETWORKS = list( //Those networks can only be accesse #define MISSING_PROGRAM 8 // Some files try to automatically launch a program. This is that failing. #define FILE_DRM 16 // Some files want to not be copied/moved. This is them complaining that you tried. #define NETWORK_FAILURE 32 + +//Flags for zone sleeping +#define ZONE_ACTIVE 1 +#define ZONE_SLEEPING 0 \ No newline at end of file diff --git a/icons/misc/debug_rebuild.dmi b/icons/misc/debug_rebuild.dmi new file mode 100644 index 00000000000..b7cde5aaf05 Binary files /dev/null and b/icons/misc/debug_rebuild.dmi differ