From 15d72e3b0e66468ebd94276ddfa4d5559aca7634 Mon Sep 17 00:00:00 2001 From: SkyMarshal Date: Thu, 26 Apr 2012 14:08:15 -0700 Subject: [PATCH 1/4] Improves how gas mixture datums are handled, reduces proc calls, commenting. Removed ghost-heating from cryo and "oxygen_agent_b" gas type. --- .../components/binary_devices/circulator.dm | 2 +- .../components/binary_devices/passive_gate.dm | 4 +- .../components/binary_devices/pump.dm | 2 +- .../components/trinary_devices/filter.dm | 7 +- .../components/trinary_devices/mixer.dm | 4 +- .../components/unary/oxygen_generator.dm | 2 +- .../components/unary/thermal_plate.dm | 8 +- .../components/unary/vent_scrubber.dm | 10 +- code/ATMOSPHERICS/datum_pipe_network.dm | 10 +- code/ATMOSPHERICS/pipes.dm | 18 +- code/FEA/DEBUG_REMOVE_BEFORE_RELEASE.dm | 3 +- code/FEA/FEA_gas_mixture.dm | 542 +++++++++--------- code/FEA/FEA_system.dm | 2 +- code/FEA/FEA_turf_tile.dm | 6 +- .../Cael_Aislinn/Rust/core_field.dm | 5 + .../Ported/ZeroPoint/SuperMatter.dm | 120 ++++ code/defines/turf.dm | 1 + .../game/events/EventProcs/ninja_equipment.dm | 2 +- code/game/machinery/atmo_control.dm | 2 +- .../atmoalter/portable_atmospherics.dm | 3 +- code/game/machinery/atmoalter/scrubber.dm | 9 +- code/game/machinery/cryo.dm | 26 +- code/game/machinery/overview.dm | 2 +- code/game/machinery/spaceheater.dm | 2 +- .../machinery/telecomms/telecommunications.dm | 2 +- code/game/mecha/equipment/tools/tools.dm | 3 +- code/game/mecha/mecha.dm | 23 +- code/game/objects/devices/PDA/PDA.dm | 2 +- code/game/objects/devices/scanners.dm | 2 +- .../objects/items/weapons/flamethrower.dm | 2 +- code/game/objects/mineral_doors.dm | 3 +- code/game/objects/tank.dm | 9 +- code/game/objects/tanks/jetpack.dm | 2 +- code/game/objects/weapons.dm | 2 + code/game/turf.dm | 1 + code/modules/admin/verbs/randomverbs.dm | 1 + code/modules/chemical/Chemistry-Reagents.dm | 14 +- code/modules/chemical/Chemistry-Recipes.dm | 1 + .../mob/living/carbon/alien/humanoid/life.dm | 8 +- .../mob/living/carbon/alien/larva/life.dm | 8 +- code/modules/mob/living/carbon/human/life.dm | 18 +- code/modules/mob/living/carbon/monkey/life.dm | 14 +- .../mob/living/silicon/pai/software.dm | 2 +- code/modules/power/turbine.dm | 8 +- code/modules/research/server.dm | 2 +- code/unused/heater.dm | 8 +- code/unused/pipe.dm | 8 +- 47 files changed, 537 insertions(+), 398 deletions(-) create mode 100644 code/WorkInProgress/Ported/ZeroPoint/SuperMatter.dm diff --git a/code/ATMOSPHERICS/components/binary_devices/circulator.dm b/code/ATMOSPHERICS/components/binary_devices/circulator.dm index 3624742d047..378aa319032 100644 --- a/code/ATMOSPHERICS/components/binary_devices/circulator.dm +++ b/code/ATMOSPHERICS/components/binary_devices/circulator.dm @@ -25,7 +25,7 @@ return null //Calculate necessary moles to transfer using PV = nRT - if((air1.total_moles() > 0) && (air1.temperature>0)) + if((air1.total_moles > 0) && (air1.temperature>0)) var/pressure_delta = (input_starting_pressure - output_starting_pressure)/2 var/transfer_moles = pressure_delta*air2.volume/(air1.temperature * R_IDEAL_GAS_EQUATION) diff --git a/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm b/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm index 60408b77b67..1163f9860af 100644 --- a/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm +++ b/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm @@ -37,7 +37,7 @@ obj/machinery/atmospherics/binary/passive_gate return 1 //Calculate necessary moles to transfer using PV = nRT - if((air1.total_moles() > 0) && (air1.temperature>0)) + if((air1.total_moles > 0) && (air1.temperature>0)) var/pressure_delta = (input_starting_pressure - output_starting_pressure)/2 //Can not have a pressure delta that would cause output_pressure > input_pressure @@ -59,4 +59,4 @@ obj/machinery/atmospherics/binary/passive_gate attack_hand(mob/user as mob) src.on = !src.on src.update_icon() - return \ No newline at end of file + return diff --git a/code/ATMOSPHERICS/components/binary_devices/pump.dm b/code/ATMOSPHERICS/components/binary_devices/pump.dm index a008536187d..7c9f1dfdfe6 100644 --- a/code/ATMOSPHERICS/components/binary_devices/pump.dm +++ b/code/ATMOSPHERICS/components/binary_devices/pump.dm @@ -65,7 +65,7 @@ obj/machinery/atmospherics/binary/pump return 1 //Calculate necessary moles to transfer using PV=nRT - if((air1.total_moles() > 0) && (air1.temperature>0)) + if((air1.total_moles > 0) && (air1.temperature>0)) var/pressure_delta = target_pressure - output_starting_pressure var/transfer_moles = pressure_delta*air2.volume/(air1.temperature * R_IDEAL_GAS_EQUATION) diff --git a/code/ATMOSPHERICS/components/trinary_devices/filter.dm b/code/ATMOSPHERICS/components/trinary_devices/filter.dm index 987081d5993..624a731e3e1 100755 --- a/code/ATMOSPHERICS/components/trinary_devices/filter.dm +++ b/code/ATMOSPHERICS/components/trinary_devices/filter.dm @@ -86,12 +86,6 @@ Filter types: filtered_out.toxins = removed.toxins removed.toxins = 0 - if(removed.trace_gases.len>0) - for(var/datum/gas/trace_gas in removed.trace_gases) - if(istype(trace_gas, /datum/gas/oxygen_agent_b)) - removed.trace_gases -= trace_gas - filtered_out.trace_gases += trace_gas - if(1) //removing O2 filtered_out.oxygen = removed.oxygen removed.oxygen = 0 @@ -115,6 +109,7 @@ Filter types: filtered_out = null + filtered_out.update_values() air2.merge(filtered_out) air3.merge(removed) diff --git a/code/ATMOSPHERICS/components/trinary_devices/mixer.dm b/code/ATMOSPHERICS/components/trinary_devices/mixer.dm index 774bd852974..595fb31fa3d 100644 --- a/code/ATMOSPHERICS/components/trinary_devices/mixer.dm +++ b/code/ATMOSPHERICS/components/trinary_devices/mixer.dm @@ -51,8 +51,8 @@ obj/machinery/atmospherics/trinary/mixer if(air2.temperature > 0) transfer_moles2 = (node2_concentration*pressure_delta)*air3.volume/(air2.temperature * R_IDEAL_GAS_EQUATION) - var/air1_moles = air1.total_moles() - var/air2_moles = air2.total_moles() + var/air1_moles = air1.total_moles + var/air2_moles = air2.total_moles if((air1_moles < transfer_moles1) || (air2_moles < transfer_moles2)) if(!transfer_moles1 || !transfer_moles2) return diff --git a/code/ATMOSPHERICS/components/unary/oxygen_generator.dm b/code/ATMOSPHERICS/components/unary/oxygen_generator.dm index 38447efa0e0..721365e6be2 100644 --- a/code/ATMOSPHERICS/components/unary/oxygen_generator.dm +++ b/code/ATMOSPHERICS/components/unary/oxygen_generator.dm @@ -33,7 +33,7 @@ obj/machinery/atmospherics/unary/oxygen_generator if(!on) return 0 - var/total_moles = air_contents.total_moles() + var/total_moles = air_contents.total_moles if(total_moles < oxygen_content) var/current_heat_capacity = air_contents.heat_capacity() diff --git a/code/ATMOSPHERICS/components/unary/thermal_plate.dm b/code/ATMOSPHERICS/components/unary/thermal_plate.dm index 7814eb57eda..868c3a73b42 100644 --- a/code/ATMOSPHERICS/components/unary/thermal_plate.dm +++ b/code/ATMOSPHERICS/components/unary/thermal_plate.dm @@ -25,18 +25,18 @@ //Get processable air sample and thermal info from environment - var/transfer_moles = 0.25 * environment.total_moles() + var/transfer_moles = 0.25 * environment.total_moles var/datum/gas_mixture/external_removed = environment.remove(transfer_moles) if (!external_removed) return radiate() - if (external_removed.total_moles() < 10) + if (external_removed.total_moles < 10) return radiate() //Get same info from connected gas - var/internal_transfer_moles = 0.25 * air_contents.total_moles() + var/internal_transfer_moles = 0.25 * air_contents.total_moles var/datum/gas_mixture/internal_removed = air_contents.remove(internal_transfer_moles) if (!internal_removed) @@ -61,7 +61,7 @@ proc/radiate() - var/internal_transfer_moles = 0.25 * air_contents.total_moles() + var/internal_transfer_moles = 0.25 * air_contents.total_moles var/datum/gas_mixture/internal_removed = air_contents.remove(internal_transfer_moles) if (!internal_removed) diff --git a/code/ATMOSPHERICS/components/unary/vent_scrubber.dm b/code/ATMOSPHERICS/components/unary/vent_scrubber.dm index 6c427baab38..5606d8113f8 100644 --- a/code/ATMOSPHERICS/components/unary/vent_scrubber.dm +++ b/code/ATMOSPHERICS/components/unary/vent_scrubber.dm @@ -98,7 +98,7 @@ if(scrubbing) if((environment.toxins>0) || (environment.carbon_dioxide>0) || (environment.trace_gases.len>0)) - var/transfer_moles = min(1, volume_rate/environment.volume)*environment.total_moles() + var/transfer_moles = min(1, volume_rate/environment.volume)*environment.total_moles //Take a gas sample var/datum/gas_mixture/removed = loc.remove_air(transfer_moles) @@ -117,15 +117,13 @@ if(removed.trace_gases.len>0) for(var/datum/gas/trace_gas in removed.trace_gases) - if(istype(trace_gas, /datum/gas/oxygen_agent_b)) - removed.trace_gases -= trace_gas - filtered_out.trace_gases += trace_gas - else if(istype(trace_gas, /datum/gas/sleeping_agent) && scrub_N2O) + if(istype(trace_gas, /datum/gas/sleeping_agent) && scrub_N2O) removed.trace_gases -= trace_gas filtered_out.trace_gases += trace_gas //Remix the resulting gases + filtered_out.update_values() air_contents.merge(filtered_out) loc.assume_air(removed) @@ -137,7 +135,7 @@ if (air_contents.return_pressure()>=50*ONE_ATMOSPHERE) return - var/transfer_moles = environment.total_moles()*(volume_rate/environment.volume) + var/transfer_moles = environment.total_moles*(volume_rate/environment.volume) var/datum/gas_mixture/removed = loc.remove_air(transfer_moles) diff --git a/code/ATMOSPHERICS/datum_pipe_network.dm b/code/ATMOSPHERICS/datum_pipe_network.dm index ce74f6cfbfc..ae4ef741307 100644 --- a/code/ATMOSPHERICS/datum_pipe_network.dm +++ b/code/ATMOSPHERICS/datum_pipe_network.dm @@ -92,8 +92,9 @@ datum/pipe_network for(var/datum/gas_mixture/gas in gases) air_transient.volume += gas.volume - total_thermal_energy += gas.thermal_energy() - total_heat_capacity += gas.heat_capacity() + var/temp_heatcap = gas.heat_capacity() + total_thermal_energy += gas.temperature*temp_heatcap + total_heat_capacity += temp_heatcap air_transient.oxygen += gas.oxygen air_transient.nitrogen += gas.nitrogen @@ -157,8 +158,9 @@ proc/equalize_gases(datum/gas_mixture/list/gases) for(var/datum/gas_mixture/gas in gases) total_volume += gas.volume - total_thermal_energy += gas.thermal_energy() - total_heat_capacity += gas.heat_capacity() + var/temp_heatcap = gas.heat_capacity() + total_thermal_energy += gas.temperature*temp_heatcap + total_heat_capacity += temp_heatcap total_oxygen += gas.oxygen total_nitrogen += gas.nitrogen diff --git a/code/ATMOSPHERICS/pipes.dm b/code/ATMOSPHERICS/pipes.dm index 78bd890fe12..74e76392002 100644 --- a/code/ATMOSPHERICS/pipes.dm +++ b/code/ATMOSPHERICS/pipes.dm @@ -381,22 +381,6 @@ obj/machinery/atmospherics/pipe ..() - oxygen_agent_b - icon = 'red_orange_pipe_tank.dmi' - name = "Pressure Tank (Oxygen + Plasma)" - - New() - air_temporary = new - air_temporary.volume = volume - air_temporary.temperature = T0C - - var/datum/gas/oxygen_agent_b/trace_gas = new - trace_gas.moles = (25*ONE_ATMOSPHERE)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature) - - air_temporary.trace_gases += trace_gas - - ..() - oxygen icon = 'blue_pipe_tank.dmi' name = "Pressure Tank (Oxygen)" @@ -599,7 +583,7 @@ obj/machinery/atmospherics/pipe O << "\red [user] has used the analyzer on \icon[icon]" var/pressure = parent.air.return_pressure() - var/total_moles = parent.air.total_moles() + var/total_moles = parent.air.total_moles user << "\blue Results of analysis of \icon[icon]" if (total_moles>0) diff --git a/code/FEA/DEBUG_REMOVE_BEFORE_RELEASE.dm b/code/FEA/DEBUG_REMOVE_BEFORE_RELEASE.dm index ed68cce383b..c3b549b10c3 100644 --- a/code/FEA/DEBUG_REMOVE_BEFORE_RELEASE.dm +++ b/code/FEA/DEBUG_REMOVE_BEFORE_RELEASE.dm @@ -441,6 +441,7 @@ turf/simulated trace_gas.moles = amount adding.trace_gases += trace_gas adding.temperature = T20C + adding.update_values() assume_air(adding) @@ -474,7 +475,7 @@ obj/indicator return "error" return "[round(GM.nitrogen/MOLES_CELLSTANDARD*10+0.5)]" else - return "[round((GM.total_moles())/MOLES_CELLSTANDARD*10+0.5)]" + return "[round((GM.total_moles)/MOLES_CELLSTANDARD*10+0.5)]" Click() diff --git a/code/FEA/FEA_gas_mixture.dm b/code/FEA/FEA_gas_mixture.dm index 7e4c565b708..5ceb602436a 100644 --- a/code/FEA/FEA_gas_mixture.dm +++ b/code/FEA/FEA_gas_mixture.dm @@ -14,13 +14,10 @@ What are the archived variables for? #define QUANTIZE(variable) (round(variable,0.0001)) datum - gas + 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 @@ -31,11 +28,12 @@ datum moles_archived = 0 gas_mixture - var + 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 @@ -47,9 +45,9 @@ datum graphic - list/datum/gas/trace_gases = list() + list/datum/gas/trace_gases = list() //Seemed to be a good idea that was abandoned - tmp + tmp //These are variables for use with the archived data oxygen_archived carbon_dioxide_archived nitrogen_archived @@ -59,227 +57,190 @@ datum graphic_archived fuel_burnt = 0 +/////////////////////////////// +//PV=nRT - related procedures// +/////////////////////////////// - proc //PV=nRT - related procedures - 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 + proc/heat_capacity() + //Purpose: Returning the heat capacity of the gas mix + //Called by: UNKNOWN + //Inputs: None + //Outputs: Heat capacity - return heat_capacity + var/heat_capacity = HEAT_CAPACITY_CALCULATION(oxygen,carbon_dioxide,nitrogen,toxins) - heat_capacity_archived() - 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 += trace_gas.moles*trace_gas.specific_heat - 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 heat_capacity - return heat_capacity_archived + proc/heat_capacity_archived() + //Purpose: Returning the archived heat capacity of the gas mix + //Called by: UNKNOWN + //Inputs: None + //Outputs: Archived heat capacity - total_moles() - var/moles = oxygen + carbon_dioxide + nitrogen + toxins + 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) - moles += trace_gas.moles + 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 moles + return heat_capacity_archived - return_pressure() - if(volume>0) - return total_moles()*R_IDEAL_GAS_EQUATION*temperature/volume - return 0 + proc/return_pressure() + //Purpose: Calculating Current Pressure + //Called by: + //Inputs: None + //Outputs: Gas pressure. - return_temperature() - return temperature + if(volume>0) + return total_moles*R_IDEAL_GAS_EQUATION*temperature/volume + return 0 - return_volume() - return max(0, volume) +// proc/return_temperature() + //Purpose: + //Inputs: + //Outputs: - thermal_energy() - return temperature*heat_capacity() +// return temperature - proc //Procedures used for very specific events - check_tile_graphic() - //returns 1 if graphic changed - graphic = null - if(toxins > MOLES_PLASMA_VISIBLE) - graphic = "plasma" +// 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 = null + if(toxins > MOLES_PLASMA_VISIBLE) + graphic = "plasma" + else + var/datum/gas/sleeping_agent = locate(/datum/gas/sleeping_agent) in trace_gases + if(sleeping_agent && (sleeping_agent.moles > 1)) + graphic = "sleeping_agent" else - var/datum/gas/sleeping_agent = locate(/datum/gas/sleeping_agent) in trace_gases - if(sleeping_agent && (sleeping_agent.moles > 1)) - graphic = "sleeping_agent" + graphic = null + + 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(fire() > 0) + reacting = 1 + + return reacting + + proc/fire() + //Purpose: Calculating any fire reactions. + //Called by: react() (See above) + //Inputs: None + //Outputs: How much fuel burned + + 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 - graphic = null + 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 - return graphic != graphic_archived + energy_released += FIRE_PLASMA_ENERGY_RELEASED * (plasma_burn_rate) - react(atom/dump_location) - var/reacting = 0 //set to 1 if a notable reaction occured (used by pipe_network) + fuel_burnt += (plasma_burn_rate)*(1+oxygen_burn_rate) - if(trace_gases.len > 0) - if(temperature > 900) - if(toxins > MINIMUM_HEAT_CAPACITY && carbon_dioxide > MINIMUM_HEAT_CAPACITY) - var/datum/gas/oxygen_agent_b/trace_gas = locate(/datum/gas/oxygen_agent_b/) in trace_gases - if(trace_gas) - var/reaction_rate = min(carbon_dioxide*0.75, toxins*0.25, trace_gas.moles*0.05) + 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() - carbon_dioxide -= reaction_rate - oxygen += reaction_rate + return fuel_burnt - trace_gas.moles -= reaction_rate*0.05 - - temperature -= (reaction_rate*20000)/heat_capacity() - - reacting = 1 - - fuel_burnt = 0 - if(temperature > FIRE_MINIMUM_TEMPERATURE_TO_EXIST) - //world << "pre [temperature], [oxygen], [toxins]" - if(fire() > 0) - reacting = 1 - //world << "post [temperature], [oxygen], [toxins]" - - return reacting - - fire() - 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 - - return fuel_burnt - - proc - archive() - //Update archived versions of variables - //Returns: 1 in all cases - - merge(datum/gas_mixture/giver) - //Merges all air from giver into self. Deletes giver. - //Returns: 1 on success (no failure cases yet) - - check_then_merge(datum/gas_mixture/giver) - //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) - //Returns: 1 on successful merge, 0 if the check failed - - remove(amount) - //Proportionally removes amount of gas from the gas_mixture - //Returns: gas_mixture with the gases removed - - remove_ratio(ratio) - //Proportionally removes amount of gas from the gas_mixture - //Returns: gas_mixture with the gases removed - - subtract(datum/gas_mixture/right_side) - //Subtracts right_side from air_mixture. Used to help turfs mingle - - check_then_remove(amount) - //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) - //Returns: gas_mixture with the gases removed or null - - copy_from(datum/gas_mixture/sample) - //Copies variables from sample - - share(datum/gas_mixture/sharer) - //Performs air sharing calculations between two gas_mixtures assuming only 1 boundary length - //Return: amount of gas exchanged (+ if sharer received) - - mimic(turf/model) - //Similar to share(...), except the model is not modified - //Return: amount of gas exchanged - - check_gas_mixture(datum/gas_mixture/sharer) - //Returns: 0 if the self-check failed then -1 if sharer-check failed then 1 if both checks pass - - check_turf(turf/model) - //Returns: 0 if self-check failed or 1 if check passes - - // check_me_then_share(datum/gas_mixture/sharer) - //Similar to share(...) but first checks to see if amount of air moved is small enough - // that group processing is still accurate for source (aborts if not) - //Returns: 1 on successful share, 0 if the check failed - - // check_me_then_mimic(turf/model) - //Similar to mimic(...) but first checks to see if amount of air moved is small enough - // that group processing is still accurate (aborts if not) - //Returns: 1 on successful mimic, 0 if the check failed - - // check_both_then_share(datum/gas_mixture/sharer) - //Similar to check_me_then_share(...) but also checks to see if amount of air moved is small enough - // that group processing is still accurate for the sharer (aborts if not) - //Returns: 0 if the self-check failed then -1 if sharer-check failed then 1 if successful share +////////////////////////////////////////////// +//Procs for general gas spread calculations.// +////////////////////////////////////////////// - temperature_mimic(turf/model, conduction_coefficient) + proc/archive() + //Purpose: Archives the current gas values + //Called by: UNKNOWN + //Inputs: None + //Outputs: 1 - temperature_share(datum/gas_mixture/sharer, conduction_coefficient) - - temperature_turf_share(turf/simulated/sharer, conduction_coefficient) - - - check_me_then_temperature_mimic(turf/model, conduction_coefficient) - - check_me_then_temperature_share(datum/gas_mixture/sharer, conduction_coefficient) - - check_both_then_temperature_share(datum/gas_mixture/sharer, conduction_coefficient) - - check_me_then_temperature_turf_share(turf/simulated/sharer, conduction_coefficient) - - compare(datum/gas_mixture/sample) - //Compares sample to self to see if within acceptable ranges that group processing may be enabled - - archive() oxygen_archived = oxygen carbon_dioxide_archived = carbon_dioxide nitrogen_archived = nitrogen @@ -295,7 +256,13 @@ datum return 1 - check_then_merge(datum/gas_mixture/giver) + 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)) \ @@ -314,7 +281,12 @@ datum return merge(giver) - merge(datum/gas_mixture/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 @@ -343,13 +315,18 @@ datum corresponding = new trace_gas.type() trace_gases += corresponding corresponding.moles += trace_gas.moles*giver.group_multiplier/group_multiplier + update_values() del(giver) return 1 - remove(amount) + 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() + var/sum = total_moles amount = min(amount,sum) //Can not take more air than tile has! if(amount <= 0) return null @@ -376,10 +353,16 @@ datum trace_gas.moles -= corresponding.moles/group_multiplier removed.temperature = temperature + update_values() + removed.update_values() return removed - remove_ratio(ratio) + 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 @@ -407,25 +390,36 @@ datum trace_gas.moles -= corresponding.moles/group_multiplier removed.temperature = temperature + update_values() + removed.update_values() return removed - check_then_remove(amount) + 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. - //Since it is all proportional, the check may be done on the gas as a whole - var/sum = total_moles() - amount = min(amount,sum) //Can not take more air than tile has! + amount = min(amount,total_moles) //Can not take more air than tile has! - if((amount > MINIMUM_AIR_RATIO_TO_SUSPEND) && (amount > sum*MINIMUM_AIR_RATIO_TO_SUSPEND)) + if((amount > MINIMUM_AIR_RATIO_TO_SUSPEND) && (amount > total_moles*MINIMUM_AIR_RATIO_TO_SUSPEND)) return 0 return remove(amount) - copy_from(datum/gas_mixture/sample) + 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) @@ -439,43 +433,14 @@ datum return 1 - subtract(datum/gas_mixture/right_side) - oxygen -= right_side.oxygen - carbon_dioxide -= right_side.carbon_dioxide - nitrogen -= right_side.nitrogen - toxins -= right_side.toxins + 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((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 - - return 1 - - /* check_me_then_share(datum/gas_mixture/sharer) - var/delta_oxygen = (oxygen_archived - sharer.oxygen_archived)/5 - var/delta_carbon_dioxide = (carbon_dioxide_archived - sharer.carbon_dioxide_archived)/5 - var/delta_nitrogen = (nitrogen_archived - sharer.nitrogen_archived)/5 - var/delta_toxins = (toxins_archived - sharer.toxins_archived)/5 - - 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 - - return share(sharer)*/ - - check_gas_mixture(datum/gas_mixture/sharer) - if(!sharer) return 0 var/delta_oxygen = (oxygen_archived - sharer.oxygen_archived)/5 var/delta_carbon_dioxide = (carbon_dioxide_archived - sharer.carbon_dioxide_archived)/5 var/delta_nitrogen = (nitrogen_archived - sharer.nitrogen_archived)/5 @@ -526,7 +491,12 @@ datum return 1 - check_turf(turf/model) + 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)/5 var/delta_carbon_dioxide = (carbon_dioxide_archived - model.carbon_dioxide)/5 var/delta_nitrogen = (nitrogen_archived - model.nitrogen)/5 @@ -549,7 +519,13 @@ datum return 1 - share(datum/gas_mixture/sharer) + 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(!sharer) return 0 var/delta_oxygen = QUANTIZE(oxygen_archived - sharer.oxygen_archived)/5 var/delta_carbon_dioxide = QUANTIZE(carbon_dioxide_archived - sharer.carbon_dioxide_archived)/5 @@ -667,6 +643,8 @@ datum 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 @@ -683,13 +661,18 @@ datum 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) + 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 - mimic(turf/model, border_multiplier) + 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)/5 var/delta_carbon_dioxide = QUANTIZE(carbon_dioxide_archived - model.carbon_dioxide)/5 var/delta_nitrogen = QUANTIZE(nitrogen_archived - model.nitrogen)/5 @@ -749,6 +732,7 @@ datum 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 @@ -761,12 +745,12 @@ datum 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) + 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 - check_both_then_temperature_share(datum/gas_mixture/sharer, conduction_coefficient) + 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() @@ -798,7 +782,7 @@ datum return 1 //Logic integrated from: temperature_share(sharer, conduction_coefficient) for efficiency - check_me_then_temperature_share(datum/gas_mixture/sharer, conduction_coefficient) + 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() @@ -826,7 +810,7 @@ datum return 1 //Logic integrated from: temperature_share(sharer, conduction_coefficient) for efficiency - check_me_then_temperature_turf_share(turf/simulated/sharer, conduction_coefficient) + proc/check_me_then_temperature_turf_share(turf/simulated/sharer, conduction_coefficient) var/delta_temperature = (temperature_archived - sharer.temperature) var/self_temperature_delta = 0 @@ -854,7 +838,7 @@ datum return 1 //Logic integrated from: temperature_turf_share(sharer, conduction_coefficient) for efficiency - check_me_then_temperature_mimic(turf/model, conduction_coefficient) + proc/check_me_then_temperature_mimic(turf/model, conduction_coefficient) var/delta_temperature = (temperature_archived - model.temperature) var/self_temperature_delta = 0 @@ -876,7 +860,7 @@ datum return 1 //Logic integrated from: temperature_mimic(model, conduction_coefficient) for efficiency - temperature_share(datum/gas_mixture/sharer, conduction_coefficient) + 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) @@ -890,7 +874,7 @@ datum temperature -= heat/(self_heat_capacity*group_multiplier) sharer.temperature += heat/(sharer_heat_capacity*sharer.group_multiplier) - temperature_mimic(turf/model, conduction_coefficient, border_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() @@ -906,7 +890,7 @@ datum else temperature -= heat/(self_heat_capacity*group_multiplier) - temperature_turf_share(turf/simulated/sharer, conduction_coefficient) + 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() @@ -918,7 +902,12 @@ datum temperature -= heat/(self_heat_capacity*group_multiplier) sharer.temperature += heat/sharer.heat_capacity - compare(datum/gas_mixture/sample) + 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((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 @@ -932,7 +921,7 @@ datum ((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(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]" @@ -959,4 +948,27 @@ datum 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/FEA/FEA_system.dm b/code/FEA/FEA_system.dm index 5be14387a74..1f63fcdb67b 100644 --- a/code/FEA/FEA_system.dm +++ b/code/FEA/FEA_system.dm @@ -147,7 +147,7 @@ datum setup() set background = 1 world << "\red \b Processing Geometry..." - sleep(1) + sleep(-1) var/start_time = world.timeofday diff --git a/code/FEA/FEA_turf_tile.dm b/code/FEA/FEA_turf_tile.dm index f42b0719915..3dd1204c2ac 100644 --- a/code/FEA/FEA_turf_tile.dm +++ b/code/FEA/FEA_turf_tile.dm @@ -25,6 +25,7 @@ turf GM.toxins = toxins GM.temperature = temperature + GM.update_values() return GM @@ -39,6 +40,7 @@ turf GM.toxins = (toxins/sum)*amount GM.temperature = temperature + GM.update_values() return GM @@ -149,6 +151,7 @@ turf air.toxins = toxins air.temperature = temperature + air.update_values() if(air_master) air_master.tiles_to_update.Add(src) @@ -189,7 +192,7 @@ turf parent.suspend_group_processing() air.merge(giver) else - if (giver.total_moles() > MINIMUM_AIR_TO_SUSPEND) + if (giver.total_moles > MINIMUM_AIR_TO_SUSPEND) reset_delay() air.merge(giver) @@ -239,7 +242,6 @@ turf if(!processing) if(air.check_tile_graphic()) update_visuals(air) - return removed else diff --git a/code/WorkInProgress/Cael_Aislinn/Rust/core_field.dm b/code/WorkInProgress/Cael_Aislinn/Rust/core_field.dm index cd738d201a1..321b835209f 100644 --- a/code/WorkInProgress/Cael_Aislinn/Rust/core_field.dm +++ b/code/WorkInProgress/Cael_Aislinn/Rust/core_field.dm @@ -161,6 +161,8 @@ Deuterium-tritium fusion: 4.5 x 10^7 K plasma_captured.toxins = round(gas_covered.toxins * transfer_ratio) plasma_captured.temperature = gas_covered.temperature gas_covered.toxins -= plasma_captured.toxins + plasma_captured.update_values() + gas_covered.update_values() held_plasma.merge(plasma_captured) // environment.merge(gas_covered) @@ -302,7 +304,9 @@ Deuterium-tritium fusion: 4.5 x 10^7 K plasma_lost.temperature = held_plasma.temperature // plasma_lost.toxins = held_plasma.toxins * loss_ratio + plasma_lost.update_values() held_plasma.toxins -= held_plasma.toxins * loss_ratio + held_plasma.update_values() // environment.merge(plasma_lost) radiation += loss_ratio * mega_energy * 0.1 @@ -310,6 +314,7 @@ Deuterium-tritium fusion: 4.5 x 10^7 K return 1 else held_plasma.toxins = 0 + held_plasma.update_values() return 0 //the !!fun!! part diff --git a/code/WorkInProgress/Ported/ZeroPoint/SuperMatter.dm b/code/WorkInProgress/Ported/ZeroPoint/SuperMatter.dm new file mode 100644 index 00000000000..9b77e9626b0 --- /dev/null +++ b/code/WorkInProgress/Ported/ZeroPoint/SuperMatter.dm @@ -0,0 +1,120 @@ +#define NITROGEN_RETARDATION_FACTOR 4 //Higher == N2 slows reaction more +#define THERMAL_RELEASE_MODIFIER 50 //Higher == less heat released during reaction +#define PLASMA_RELEASE_MODIFIER 750 //Higher == less plasma released by reaction +#define OXYGEN_RELEASE_MODIFIER 1500 //Higher == less oxygen released at high temperature/power +#define REACTION_POWER_MODIFIER 1.1 //Higher == more overall power + +/obj/machinery/engine/supermatter + name = "Supermatter" + desc = "A strangely translucent and iridescent crystal. \red You get headaches just from looking at it." + icon = 'engine.dmi' + icon_state = "darkmatter" + density = 1 + anchored = 1 + + var/gasefficency = 0.25 + + var/det = 0 + var/previousdet = 0 + var/const/explosiondet = 3500 + + var/const/warningtime = 50 // Make the CORE OVERLOAD message repeat only every aprox. ?? seconds + var/lastwarning = 0 // Time in 1/10th of seconds since the last sent warning + +/obj/machinery/engine/klaxon + name = "Emergency Klaxon" + icon = 'engine.dmi' + icon_state = "darkmatter" + density = 1 + anchored = 1 + var/obj/machinery/engine/supermatter/sup + +/obj/machinery/engine/klaxon/process() + if(!sup) + for(var/obj/machinery/engine/supermatter/T in world) + sup = T + break + if(sup.det >= 1) + return + +/obj/machinery/engine/supermatter/process() + + var/turf/simulated/L = loc + + //Ok, get the air from the turf + var/datum/gas_mixture/env = L.return_air() + + //Remove gas from surrounding area + var/transfer_moles = gasefficency * env.total_moles + var/datum/gas_mixture/removed = env.remove(transfer_moles) + + previousdet = det + det += (removed.temperature - 1000) / 150 + det = max(det, 0) + + if(det > 0 && removed.temperature > 1000) // while the core is still damaged and it's still worth noting its status + if((world.realtime - lastwarning) / 10 >= warningtime) + lastwarning = world.realtime + if(explosiondet - det <= 300) + radioalert("CORE EXPLOSION IMMINENT","Core control computer") + else if(det >= previousdet) // The damage is still going up + radioalert("CORE OVERLOAD","Core control computer") + else // Phew, we're safe + radioalert("Core returning to safe operating levels.","Core control computer") + + if(det > explosiondet) + roundinfo.core = 1 + //proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, force = 0) + explosion(src.loc,8,15,20,30,1) + det = 0 + + if (!removed) + return 1 + + var/power = max(round((removed.temperature - T0C) / 20), 0) //Total laser power plus an overload factor + + //Get the collective laser power + for(var/dir in cardinal) + var/turf/T = get_step(L, dir) + for(var/obj/effect/beam/e_beam/item in T) + power += item.power + + //Ok, 100% oxygen atmosphere = best reaction + //Maxes out at 100% oxygen pressure + var/oxygen = max(min((removed.oxygen - (removed.nitrogen * NITROGEN_RETARDATION_FACTOR)) / MOLES_CELLSTANDARD, 1), 0) + + var/device_energy = oxygen * power + + device_energy *= removed.temperature / T0C + + device_energy = round(device_energy * REACTION_POWER_MODIFIER) + + //To figure out how much temperature to add each tick, consider that at one atmosphere's worth + //of pure oxygen, with all four lasers firing at standard energy and no N2 present, at room temperature + //that the device energy is around 2140. At that stage, we don't want too much heat to be put out + //Since the core is effectively "cold" + + //Also keep in mind we are only adding this temperature to (efficiency)% of the one tile the rock + //is on. An increase of 4*C @ 25% efficiency here results in an increase of 1*C / (#tilesincore) overall. + removed.temperature += max((device_energy / THERMAL_RELEASE_MODIFIER), 0) + + removed.temperature = min(removed.temperature, 1500) + + //Calculate how much gas to release + removed.toxins += max(round(device_energy / PLASMA_RELEASE_MODIFIER), 0) + + removed.oxygen += max(round((device_energy + removed.temperature - T0C) / OXYGEN_RELEASE_MODIFIER), 0) + + env.merge(removed) + +//Not functional currently. -- SkyMarshal +/* + for(var/mob/living/carbon/l in view(src, 6)) // you have to be seeing the core to get hallucinations + if(prob(10) && !(l.glasses && istype(l.glasses, /obj/item/clothing/glasses/meson))) + l.hallucination = 50 +*/ + for(var/mob/living/l in view(src,3)) + l.bruteloss += 50 + l.updatehealth() + + return 1 \ No newline at end of file diff --git a/code/defines/turf.dm b/code/defines/turf.dm index c1bddae221f..e33bb523029 100644 --- a/code/defines/turf.dm +++ b/code/defines/turf.dm @@ -301,6 +301,7 @@ napalm.toxins = toxinsToDeduce napalm.temperature = 400+T0C + napalm.update_values() target_tile.assume_air(napalm) spawn (0) target_tile.hotspot_expose(temperature, 400) diff --git a/code/game/events/EventProcs/ninja_equipment.dm b/code/game/events/EventProcs/ninja_equipment.dm index d0bc9efdaac..bf09f2f7c33 100644 --- a/code/game/events/EventProcs/ninja_equipment.dm +++ b/code/game/events/EventProcs/ninja_equipment.dm @@ -311,7 +311,7 @@ ________________________________________________________________________________ var/datum/gas_mixture/environment = T.return_air() var/pressure = environment.return_pressure() - var/total_moles = environment.total_moles() + var/total_moles = environment.total_moles dat += "Air Pressure: [round(pressure,0.1)] kPa" diff --git a/code/game/machinery/atmo_control.dm b/code/game/machinery/atmo_control.dm index e0274cf54dc..23013ab1d3a 100644 --- a/code/game/machinery/atmo_control.dm +++ b/code/game/machinery/atmo_control.dm @@ -40,7 +40,7 @@ obj/machinery/air_sensor signal.data["temperature"] = round(air_sample.temperature,0.1) if(output>4) - var/total_moles = air_sample.total_moles() + var/total_moles = air_sample.total_moles if(total_moles > 0) if(output&4) signal.data["oxygen"] = round(100*air_sample.oxygen/total_moles,0.1) diff --git a/code/game/machinery/atmoalter/portable_atmospherics.dm b/code/game/machinery/atmoalter/portable_atmospherics.dm index 5130c37be47..a15e0550c41 100644 --- a/code/game/machinery/atmoalter/portable_atmospherics.dm +++ b/code/game/machinery/atmoalter/portable_atmospherics.dm @@ -15,6 +15,7 @@ air_contents.volume = volume air_contents.temperature = T20C + air_contents.update_values() return 1 @@ -110,7 +111,7 @@ O << "\red [user] has used [W] on \icon[icon]" if(air_contents) var/pressure = air_contents.return_pressure() - var/total_moles = air_contents.total_moles() + var/total_moles = air_contents.total_moles user << "\blue Results of analysis of \icon[icon]" if (total_moles>0) diff --git a/code/game/machinery/atmoalter/scrubber.dm b/code/game/machinery/atmoalter/scrubber.dm index c3ea2164a1d..94933468428 100644 --- a/code/game/machinery/atmoalter/scrubber.dm +++ b/code/game/machinery/atmoalter/scrubber.dm @@ -56,7 +56,7 @@ environment = holding.air_contents else environment = loc.return_air() - var/transfer_moles = min(1, volume_rate/environment.volume)*environment.total_moles() + var/transfer_moles = min(1, volume_rate/environment.volume)*environment.total_moles //Take a gas sample var/datum/gas_mixture/removed @@ -83,12 +83,7 @@ if(istype(trace_gas, /datum/gas/sleeping_agent)) removed.trace_gases -= trace_gas filtered_out.trace_gases += trace_gas - - if(removed.trace_gases.len>0) - for(var/datum/gas/trace_gas in removed.trace_gases) - if(istype(trace_gas, /datum/gas/oxygen_agent_b)) - removed.trace_gases -= trace_gas - filtered_out.trace_gases += trace_gas + filtered_out.update_values() //Remix the resulting gases air_contents.merge(filtered_out) diff --git a/code/game/machinery/cryo.dm b/code/game/machinery/cryo.dm index 791b3db0617..eed8e9fd64d 100644 --- a/code/game/machinery/cryo.dm +++ b/code/game/machinery/cryo.dm @@ -44,7 +44,7 @@ if(air_contents) temperature_archived = air_contents.temperature - heat_gas_contents() +// heat_gas_contents() expel_gas() if(abs(temperature_archived-air_contents.temperature) > 1) @@ -156,7 +156,7 @@ add_overlays() process_occupant() - if(air_contents.total_moles() < 10) + if(air_contents.total_moles < 10) return if(occupant) if(occupant.stat == 2) @@ -185,22 +185,24 @@ if(next_trans == 10) next_trans = 0 - heat_gas_contents() - if(air_contents.total_moles() < 1) - return - var/air_heat_capacity = air_contents.heat_capacity() - var/combined_heat_capacity = current_heat_capacity + air_heat_capacity - if(combined_heat_capacity > 0) - var/combined_energy = T20C*current_heat_capacity + air_heat_capacity*air_contents.temperature - air_contents.temperature = combined_energy/combined_heat_capacity +//Fucking ghost-heating. +// heat_gas_contents() +// if(air_contents.total_moles < 1) +// return +// var/air_heat_capacity = air_contents.heat_capacity() +// var/combined_heat_capacity = current_heat_capacity + air_heat_capacity +// if(combined_heat_capacity > 0) +// var/combined_energy = T20C*current_heat_capacity + air_heat_capacity*air_contents.temperature +// air_contents.temperature = combined_energy/combined_heat_capacity expel_gas() - if(air_contents.total_moles() < 1) + if(air_contents.total_moles < 1) return var/datum/gas_mixture/expel_gas = new - var/remove_amount = air_contents.total_moles()/100 + var/remove_amount = air_contents.total_moles/100 expel_gas = air_contents.remove(remove_amount) expel_gas.temperature = T20C // Lets expel hot gas and see if that helps people not die as they are removed + expel_gas.update_values() loc.assume_air(expel_gas) go_out() diff --git a/code/game/machinery/overview.dm b/code/game/machinery/overview.dm index a278fd1f1ab..185c33ae6f2 100644 --- a/code/game/machinery/overview.dm +++ b/code/game/machinery/overview.dm @@ -208,7 +208,7 @@ if("/turf/simulated/floor", "/turf/simulated/floor/engine") var/datum/gas_mixture/environment = T.return_air() - var/turf_total = environment.total_moles() + var/turf_total = environment.total_moles var/t1 = turf_total / MOLES_CELLSTANDARD * 175 if(t1<=100) diff --git a/code/game/machinery/spaceheater.dm b/code/game/machinery/spaceheater.dm index 128f4190576..27436096cf6 100644 --- a/code/game/machinery/spaceheater.dm +++ b/code/game/machinery/spaceheater.dm @@ -166,7 +166,7 @@ var/datum/gas_mixture/env = L.return_air() if(env.temperature < (set_temperature+T0C)) - var/transfer_moles = 0.25 * env.total_moles() + var/transfer_moles = 0.25 * env.total_moles var/datum/gas_mixture/removed = env.remove(transfer_moles) diff --git a/code/game/machinery/telecomms/telecommunications.dm b/code/game/machinery/telecomms/telecommunications.dm index b9e042240ca..3881a10b6b8 100644 --- a/code/game/machinery/telecomms/telecommunications.dm +++ b/code/game/machinery/telecomms/telecommunications.dm @@ -205,7 +205,7 @@ var/datum/gas_mixture/env = L.return_air() if(env.temperature < (heat_amt+T0C)) - var/transfer_moles = 0.25 * env.total_moles() + var/transfer_moles = 0.25 * env.total_moles var/datum/gas_mixture/removed = env.remove(transfer_moles) diff --git a/code/game/mecha/equipment/tools/tools.dm b/code/game/mecha/equipment/tools/tools.dm index 532aea59a36..21d019eec23 100644 --- a/code/game/mecha/equipment/tools/tools.dm +++ b/code/game/mecha/equipment/tools/tools.dm @@ -853,8 +853,9 @@ destroy() else GM.toxins += 5 - GM.temperature = istype(T) ? T.air.return_temperature() : T20C + GM.temperature = istype(T) ? T.air.temperature : T20C T.visible_message("The [src] suddenly disgorges a cloud of plasma.") + GM.update_values() T.assume_air(GM) return diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index cba65072aed..4b7fd385845 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -121,6 +121,7 @@ cabin_air.volume = 200 cabin_air.oxygen = O2STANDARD*cabin_air.volume/(R_IDEAL_GAS_EQUATION*cabin_air.temperature) cabin_air.nitrogen = N2STANDARD*cabin_air.volume/(R_IDEAL_GAS_EQUATION*cabin_air.temperature) + cabin_air.update_values() return cabin_air /obj/mecha/proc/add_radio() @@ -847,11 +848,11 @@ /obj/mecha/proc/return_temperature() . = 0 if(use_internal_tank) - . = cabin_air.return_temperature() + . = cabin_air.temperature else var/datum/gas_mixture/t_air = get_turf_air() if(t_air) - . = t_air.return_temperature() + . = t_air.temperature return /obj/mecha/proc/connect(obj/machinery/atmospherics/portables_connector/new_port) @@ -1665,7 +1666,7 @@ delay = 20 process(var/obj/mecha/mecha) - if(mecha.cabin_air && mecha.cabin_air.return_volume() > 0) + if(mecha.cabin_air && mecha.cabin_air.volume > 0) var/delta = mecha.cabin_air.temperature - T20C mecha.cabin_air.temperature -= max(-10, min(10, round(delta/4,0.1))) return @@ -1683,8 +1684,8 @@ var/pressure_delta = min(release_pressure - cabin_pressure, (tank_air.return_pressure() - cabin_pressure)/2) var/transfer_moles = 0 if(pressure_delta > 0) //cabin pressure lower than release pressure - if(tank_air.return_temperature() > 0) - transfer_moles = pressure_delta*cabin_air.return_volume()/(cabin_air.return_temperature() * R_IDEAL_GAS_EQUATION) + if(tank_air.temperature > 0) + transfer_moles = pressure_delta*max(0, cabin_air.volume)/(cabin_air.temperature * R_IDEAL_GAS_EQUATION) var/datum/gas_mixture/removed = tank_air.remove(transfer_moles) cabin_air.merge(removed) else if(pressure_delta < 0) //cabin pressure higher than release pressure @@ -1693,7 +1694,7 @@ if(t_air) pressure_delta = min(cabin_pressure - t_air.return_pressure(), pressure_delta) if(pressure_delta > 0) //if location pressure is lower than cabin pressure - transfer_moles = pressure_delta*cabin_air.return_volume()/(cabin_air.return_temperature() * R_IDEAL_GAS_EQUATION) + transfer_moles = pressure_delta*max(0, cabin_air.volume)/(cabin_air.temperature * R_IDEAL_GAS_EQUATION) var/datum/gas_mixture/removed = cabin_air.remove(transfer_moles) if(t_air) t_air.merge(removed) @@ -1726,12 +1727,12 @@ if(mecha.internal_tank.return_pressure()>mecha.internal_tank.maximum_pressure && !(mecha.hasInternalDamage(MECHA_INT_TANK_BREACH))) mecha.setInternalDamage(MECHA_INT_TANK_BREACH) var/datum/gas_mixture/int_tank_air = mecha.internal_tank.return_air() - if(int_tank_air && int_tank_air.return_volume()>0) //heat the air_contents + if(int_tank_air && int_tank_air.volume >0) //heat the air_contents int_tank_air.temperature = min(6000+T0C, int_tank_air.temperature+rand(10,15)) - if(mecha.cabin_air && mecha.cabin_air.return_volume()>0) - mecha.cabin_air.temperature = min(6000+T0C, mecha.cabin_air.return_temperature()+rand(10,15)) - if(mecha.cabin_air.return_temperature()>mecha.max_temperature/2) - mecha.take_damage(4/round(mecha.max_temperature/mecha.cabin_air.return_temperature(),0.1),"fire") + if(mecha.cabin_air && mecha.cabin_air.volume>0) + mecha.cabin_air.temperature = min(6000+T0C, mecha.cabin_air.temperature+rand(10,15)) + if(mecha.cabin_air.temperature>mecha.max_temperature/2) + mecha.take_damage(4/round(mecha.max_temperature/mecha.cabin_air.temperature,0.1),"fire") if(mecha.hasInternalDamage(MECHA_INT_TEMP_CONTROL)) //stop the mecha_preserve_temp loop datum mecha.pr_int_temp_processor.stop() if(mecha.hasInternalDamage(MECHA_INT_TANK_BREACH)) //remove some air from internal tank diff --git a/code/game/objects/devices/PDA/PDA.dm b/code/game/objects/devices/PDA/PDA.dm index 6c502d18c10..39cec7c3054 100755 --- a/code/game/objects/devices/PDA/PDA.dm +++ b/code/game/objects/devices/PDA/PDA.dm @@ -331,7 +331,7 @@ var/datum/gas_mixture/environment = T.return_air() var/pressure = environment.return_pressure() - var/total_moles = environment.total_moles() + var/total_moles = environment.total_moles dat += "Air Pressure: [round(pressure,0.1)] kPa
" diff --git a/code/game/objects/devices/scanners.dm b/code/game/objects/devices/scanners.dm index 17b62e1f119..8d0211e7f29 100644 --- a/code/game/objects/devices/scanners.dm +++ b/code/game/objects/devices/scanners.dm @@ -369,7 +369,7 @@ MASS SPECTROMETER var/datum/gas_mixture/environment = location.return_air() var/pressure = environment.return_pressure() - var/total_moles = environment.total_moles() + var/total_moles = environment.total_moles user.show_message("\blue Results:", 1) if(abs(pressure - ONE_ATMOSPHERE) < 10) diff --git a/code/game/objects/items/weapons/flamethrower.dm b/code/game/objects/items/weapons/flamethrower.dm index d206312b0a2..7ed926c801d 100644 --- a/code/game/objects/items/weapons/flamethrower.dm +++ b/code/game/objects/items/weapons/flamethrower.dm @@ -133,7 +133,7 @@ for (var/mob/O in viewers(user, null)) O << "\red [user] has used the analyzer on \icon[icon]" var/pressure = src.ptank.air_contents.return_pressure() - var/total_moles = src.ptank.air_contents.total_moles() + var/total_moles = src.ptank.air_contents.total_moles user << "\blue Results of analysis of \icon[icon]" if (total_moles>0) diff --git a/code/game/objects/mineral_doors.dm b/code/game/objects/mineral_doors.dm index 17118f65f19..310cdfd8805 100644 --- a/code/game/objects/mineral_doors.dm +++ b/code/game/objects/mineral_doors.dm @@ -234,6 +234,7 @@ napalm.toxins = toxinsToDeduce napalm.temperature = 400+T0C + napalm.update_values() target_tile.assume_air(napalm) spawn (0) target_tile.hotspot_expose(temperature, 400) @@ -304,4 +305,4 @@ isSwitchingStates = 0 Dismantle(devastated = 0) - del(src) \ No newline at end of file + del(src) diff --git a/code/game/objects/tank.dm b/code/game/objects/tank.dm index cb2bb08bc53..ed1cdbd865b 100644 --- a/code/game/objects/tank.dm +++ b/code/game/objects/tank.dm @@ -210,7 +210,7 @@ var/pressure = air_contents.return_pressure() - var/total_moles = air_contents.total_moles() + var/total_moles = air_contents.total_moles user << "\blue Results of analysis of \icon[icon]" if (total_moles>0) @@ -244,6 +244,7 @@ src.air_contents = new /datum/gas_mixture() src.air_contents.volume = volume //liters src.air_contents.temperature = T20C + air_contents.update_values() processing_objects.Add(src) @@ -258,6 +259,7 @@ ..() /obj/item/weapon/tank/examine() + set src in oview() var/obj/icon = src if (istype(src.loc, /obj/item/assembly)) icon = src.loc @@ -290,6 +292,7 @@ src.air_contents.oxygen = (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * O2STANDARD src.air_contents.nitrogen = (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * N2STANDARD + air_contents.update_values() return @@ -302,17 +305,19 @@ trace_gas.moles = (3*ONE_ATMOSPHERE)*70/(R_IDEAL_GAS_EQUATION*T20C) * N2STANDARD src.air_contents.trace_gases += trace_gas + air_contents.update_values() return /obj/item/weapon/tank/plasma/New() ..() src.air_contents.toxins = (3*ONE_ATMOSPHERE)*70/(R_IDEAL_GAS_EQUATION*T20C) + air_contents.update_values() return /obj/item/weapon/tank/plasma/proc/release() - var/datum/gas_mixture/removed = air_contents.remove(air_contents.total_moles()) + var/datum/gas_mixture/removed = air_contents.remove(air_contents.total_moles) loc.assume_air(removed) diff --git a/code/game/objects/tanks/jetpack.dm b/code/game/objects/tanks/jetpack.dm index 87552b99486..7e829f4a9a0 100644 --- a/code/game/objects/tanks/jetpack.dm +++ b/code/game/objects/tanks/jetpack.dm @@ -53,7 +53,7 @@ proc/allow_thrust(num, mob/living/user as mob) if(!(src.on)) return 0 - if((num < 0.005 || src.air_contents.total_moles() < num)) + if((num < 0.005 || src.air_contents.total_moles < num)) src.ion_trail.stop() return 0 diff --git a/code/game/objects/weapons.dm b/code/game/objects/weapons.dm index 15c395310b6..6d04a7d4ea0 100644 --- a/code/game/objects/weapons.dm +++ b/code/game/objects/weapons.dm @@ -38,6 +38,7 @@ trace_gas.moles = 30 payload += trace_gas + payload.update_values() target.air.merge(payload) @@ -53,6 +54,7 @@ var/datum/gas_mixture/payload = new payload.toxins = 30 + payload.update_values() target.air.merge(payload) diff --git a/code/game/turf.dm b/code/game/turf.dm index 7932512bdab..ac32981a41f 100644 --- a/code/game/turf.dm +++ b/code/game/turf.dm @@ -903,6 +903,7 @@ var/list/plating_icons = list("plating","platingdmg1","platingdmg2","platingdmg3 trace_gas.moles = 2000 adding.trace_gases += trace_gas adding.temperature = T20C + adding.update_values() assume_air(adding) diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index 774c8dece0e..82358e2e624 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -719,6 +719,7 @@ Traitors and the like can also be revived with the previous role mostly intact. T.air.nitrogen = T.nitrogen T.air.toxins = T.toxins T.air.temperature = T.temperature + T.air.update_values() // make things update properly T.assume_air(new /datum/gas_mixture()) diff --git a/code/modules/chemical/Chemistry-Reagents.dm b/code/modules/chemical/Chemistry-Reagents.dm index e0755c21585..ca89fcc58f3 100644 --- a/code/modules/chemical/Chemistry-Reagents.dm +++ b/code/modules/chemical/Chemistry-Reagents.dm @@ -282,7 +282,7 @@ datum var/hotspot = (locate(/obj/effect/hotspot) in T) if(hotspot && !istype(T, /turf/space)) - var/datum/gas_mixture/lowertemp = T.remove_air( T:air:total_moles() ) + var/datum/gas_mixture/lowertemp = T.remove_air( T:air:total_moles ) lowertemp.temperature = max( min(lowertemp.temperature-2000,lowertemp.temperature / 2) ,0) lowertemp.react() T.assume_air(lowertemp) @@ -293,7 +293,7 @@ datum var/turf/T = get_turf(O) var/hotspot = (locate(/obj/effect/hotspot) in T) if(hotspot && !istype(T, /turf/space)) - var/datum/gas_mixture/lowertemp = T.remove_air( T:air:total_moles() ) + var/datum/gas_mixture/lowertemp = T.remove_air( T:air:total_moles ) lowertemp.temperature = max( min(lowertemp.temperature-2000,lowertemp.temperature / 2) ,0) lowertemp.react() T.assume_air(lowertemp) @@ -543,12 +543,14 @@ datum var/datum/gas_mixture/napalm = new napalm.oxygen = volume*10 napalm.temperature = T0C + napalm.update_values() the_turf.assume_air(napalm) reaction_turf(var/turf/T, var/volume) src = null var/datum/gas_mixture/napalm = new napalm.oxygen = volume*10 napalm.temperature = T0C + napalm.update_values() T.assume_air(napalm) return @@ -571,12 +573,14 @@ datum var/datum/gas_mixture/napalm = new napalm.nitrogen = volume*10 napalm.temperature = T0C + napalm.update_values() the_turf.assume_air(napalm) reaction_turf(var/turf/T, var/volume) src = null var/datum/gas_mixture/napalm = new napalm.nitrogen = volume*10 napalm.temperature = T0C + napalm.update_values() T.assume_air(napalm) return @@ -1051,12 +1055,14 @@ datum var/datum/gas_mixture/napalm = new napalm.toxins = volume*10 napalm.temperature = T0C + napalm.update_values() the_turf.assume_air(napalm) reaction_turf(var/turf/T, var/volume) src = null var/datum/gas_mixture/napalm = new napalm.toxins = volume*10 napalm.temperature = T0C + napalm.update_values() T.assume_air(napalm) return on_mob_life(var/mob/living/M as mob) @@ -1168,6 +1174,7 @@ datum var/datum/gas/volatile_fuel/fuel = new fuel.moles = 5 napalm.trace_gases += fuel + napalm.update_values() the_turf.assume_air(napalm) reaction_turf(var/turf/T, var/volume) src = null @@ -1175,6 +1182,7 @@ datum var/datum/gas/volatile_fuel/fuel = new fuel.moles = 5 napalm.trace_gases += fuel + napalm.update_values() T.assume_air(napalm) return @@ -2154,7 +2162,7 @@ datum T.wet_overlay = null var/hotspot = (locate(/obj/effect/hotspot) in T) if(hotspot) - var/datum/gas_mixture/lowertemp = T.remove_air( T:air:total_moles() ) + var/datum/gas_mixture/lowertemp = T.remove_air( T:air:total_moles ) lowertemp.temperature = max( min(lowertemp.temperature-2000,lowertemp.temperature / 2) ,0) lowertemp.react() T.assume_air(lowertemp) diff --git a/code/modules/chemical/Chemistry-Recipes.dm b/code/modules/chemical/Chemistry-Recipes.dm index 89c44b841cf..10914601d01 100644 --- a/code/modules/chemical/Chemistry-Recipes.dm +++ b/code/modules/chemical/Chemistry-Recipes.dm @@ -357,6 +357,7 @@ datum napalm.toxins = created_volume*10 napalm.temperature = 400+T0C + napalm.update_values() target_tile.assume_air(napalm) spawn (0) target_tile.hotspot_expose(700, 400) diff --git a/code/modules/mob/living/carbon/alien/humanoid/life.dm b/code/modules/mob/living/carbon/alien/humanoid/life.dm index 6356a385efe..38bf7ceb528 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/life.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/life.dm @@ -211,7 +211,7 @@ breath_moles = (ONE_ATMOSPHERE*BREATH_VOLUME/R_IDEAL_GAS_EQUATION*environment.temperature) else*/ // Not enough air around, take a percentage of what's there to model this properly - breath_moles = environment.total_moles()*BREATH_PERCENTAGE + breath_moles = environment.total_moles*BREATH_PERCENTAGE breath = loc.remove_air(breath_moles) @@ -259,15 +259,15 @@ if(src.nodamage) return - if(!breath || (breath.total_moles() == 0)) + if(!breath || (breath.total_moles == 0)) //Aliens breathe in vaccuum return 0 var/toxins_used = 0 - var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME + var/breath_pressure = (breath.total_moles*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME //Partial pressure of the toxins in our breath - var/Toxins_pp = (breath.toxins/breath.total_moles())*breath_pressure + var/Toxins_pp = (breath.toxins/breath.total_moles)*breath_pressure if(Toxins_pp) // Detect toxins in air diff --git a/code/modules/mob/living/carbon/alien/larva/life.dm b/code/modules/mob/living/carbon/alien/larva/life.dm index 334676870a8..a79f290a0dc 100644 --- a/code/modules/mob/living/carbon/alien/larva/life.dm +++ b/code/modules/mob/living/carbon/alien/larva/life.dm @@ -186,7 +186,7 @@ breath_moles = (ONE_ATMOSPHERE*BREATH_VOLUME/R_IDEAL_GAS_EQUATION*environment.temperature) else*/ // Not enough air around, take a percentage of what's there to model this properly - breath_moles = environment.total_moles()*BREATH_PERCENTAGE + breath_moles = environment.total_moles*BREATH_PERCENTAGE breath = loc.remove_air(breath_moles) @@ -234,15 +234,15 @@ if(nodamage) return - if(!breath || (breath.total_moles() == 0)) + if(!breath || (breath.total_moles == 0)) //Aliens breathe in vaccuum return 0 var/toxins_used = 0 - var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME + var/breath_pressure = (breath.total_moles*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME //Partial pressure of the toxins in our breath - var/Toxins_pp = (breath.toxins/breath.total_moles())*breath_pressure + var/Toxins_pp = (breath.toxins/breath.total_moles)*breath_pressure if(Toxins_pp) // Detect toxins in air diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 792b68e56a2..9e2070097b8 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -409,7 +409,7 @@ breath_moles = (ONE_ATMOSPHERE*BREATH_VOLUME/R_IDEAL_GAS_EQUATION*environment.temperature) else*/ // Not enough air around, take a percentage of what's there to model this properly - breath_moles = environment.total_moles()*BREATH_PERCENTAGE + breath_moles = environment.total_moles*BREATH_PERCENTAGE breath = loc.remove_air(breath_moles) @@ -473,7 +473,7 @@ if(nodamage || (mutations & mNobreath)) return - if(!breath || (breath.total_moles() == 0)) + if(!breath || (breath.total_moles == 0)) if(reagents.has_reagent("inaprovaline")) return adjustOxyLoss(HUMAN_MAX_OXYLOSS) @@ -491,15 +491,15 @@ var/SA_para_min = 1 var/SA_sleep_min = 5 var/oxygen_used = 0 - var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME + var/breath_pressure = (breath.total_moles*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME //Partial pressure of the O2 in our breath - var/O2_pp = (breath.oxygen/breath.total_moles())*breath_pressure + var/O2_pp = (breath.oxygen/breath.total_moles)*breath_pressure // Same, but for the toxins - var/Toxins_pp = (breath.toxins/breath.total_moles())*breath_pressure + var/Toxins_pp = (breath.toxins/breath.total_moles)*breath_pressure // And CO2, lets say a PP of more than 10 will be bad (It's a little less really, but eh, being passed out all round aint no fun) - var/CO2_pp = (breath.carbon_dioxide/breath.total_moles())*breath_pressure // Tweaking to fit the hacky bullshit I've done with atmo -- TLE - //var/CO2_pp = (breath.carbon_dioxide/breath.total_moles())*0.5 // The default pressure value + var/CO2_pp = (breath.carbon_dioxide/breath.total_moles)*breath_pressure // Tweaking to fit the hacky bullshit I've done with atmo -- TLE + //var/CO2_pp = (breath.carbon_dioxide/breath.total_moles)*0.5 // The default pressure value if(O2_pp < safe_oxygen_min) // Too little oxygen if(prob(20) && isbreathing) @@ -548,7 +548,7 @@ if(breath.trace_gases.len) // If there's some other shit in the air lets deal with it here. for(var/datum/gas/sleeping_agent/SA in breath.trace_gases) - var/SA_pp = (SA.moles/breath.total_moles())*breath_pressure + var/SA_pp = (SA.moles/breath.total_moles)*breath_pressure if(SA_pp > SA_para_min) // Enough to make us paralysed for a bit Paralyse(3) // 3 gives them one second to wake up and run away a bit! if(SA_pp > SA_sleep_min) // Enough to make us sleep as well @@ -1532,5 +1532,5 @@ snippets src << "\red You collapse from heat exaustion!" plcheck = t_plasma oxcheck = t_oxygen - G.turf_add(T, G.total_moles()) + G.turf_add(T, G.total_moles) */ \ No newline at end of file diff --git a/code/modules/mob/living/carbon/monkey/life.dm b/code/modules/mob/living/carbon/monkey/life.dm index 266bd3fc601..70489c1117a 100644 --- a/code/modules/mob/living/carbon/monkey/life.dm +++ b/code/modules/mob/living/carbon/monkey/life.dm @@ -206,7 +206,7 @@ var/obj/location_as_object = loc breath = location_as_object.handle_internal_lifeform(src, BREATH_VOLUME) else if(istype(loc, /turf/)) - var/breath_moles = environment.total_moles()*BREATH_PERCENTAGE + var/breath_moles = environment.total_moles*BREATH_PERCENTAGE breath = loc.remove_air(breath_moles) // Handle chem smoke effect -- Doohl @@ -260,7 +260,7 @@ if(src.nodamage) return - if(!breath || (breath.total_moles() == 0)) + if(!breath || (breath.total_moles == 0)) adjustOxyLoss(7) oxygen_alert = max(oxygen_alert, 1) @@ -274,14 +274,14 @@ var/SA_para_min = 0.5 var/SA_sleep_min = 5 var/oxygen_used = 0 - var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME + var/breath_pressure = (breath.total_moles*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME //Partial pressure of the O2 in our breath - var/O2_pp = (breath.oxygen/breath.total_moles())*breath_pressure + var/O2_pp = (breath.oxygen/breath.total_moles)*breath_pressure // Same, but for the toxins - var/Toxins_pp = (breath.toxins/breath.total_moles())*breath_pressure + var/Toxins_pp = (breath.toxins/breath.total_moles)*breath_pressure // And CO2, lets say a PP of more than 10 will be bad (It's a little less really, but eh, being passed out all round aint no fun) - var/CO2_pp = (breath.carbon_dioxide/breath.total_moles())*breath_pressure + var/CO2_pp = (breath.carbon_dioxide/breath.total_moles)*breath_pressure if(O2_pp < safe_oxygen_min) // Too little oxygen if(prob(20)) @@ -329,7 +329,7 @@ if(breath.trace_gases.len) // If there's some other shit in the air lets deal with it here. for(var/datum/gas/sleeping_agent/SA in breath.trace_gases) - var/SA_pp = (SA.moles/breath.total_moles())*breath_pressure + var/SA_pp = (SA.moles/breath.total_moles)*breath_pressure if(SA_pp > SA_para_min) // Enough to make us paralysed for a bit Paralyse(3) // 3 gives them one second to wake up and run away a bit! if(SA_pp > SA_sleep_min) // Enough to make us sleep as well diff --git a/code/modules/mob/living/silicon/pai/software.dm b/code/modules/mob/living/silicon/pai/software.dm index 30338c21fc4..e233ff3d990 100644 --- a/code/modules/mob/living/silicon/pai/software.dm +++ b/code/modules/mob/living/silicon/pai/software.dm @@ -508,7 +508,7 @@ var/datum/gas_mixture/environment = T.return_air() var/pressure = environment.return_pressure() - var/total_moles = environment.total_moles() + var/total_moles = environment.total_moles dat += "Air Pressure: [round(pressure,0.1)] kPa
" diff --git a/code/modules/power/turbine.dm b/code/modules/power/turbine.dm index adf09a57d29..e851c2d6b40 100644 --- a/code/modules/power/turbine.dm +++ b/code/modules/power/turbine.dm @@ -66,7 +66,7 @@ return rpm = 0.9* rpm + 0.1 * rpmtarget var/datum/gas_mixture/environment = inturf.return_air() - var/transfer_moles = environment.total_moles()/10 + var/transfer_moles = environment.total_moles/10 //var/transfer_moles = rpm/10000*capacity var/datum/gas_mixture/removed = inturf.remove_air(transfer_moles) gas_contained.merge(removed) @@ -122,14 +122,14 @@ lastgen = ((compressor.rpm / TURBGENQ)**TURBGENG) *TURBGENQ add_avail(lastgen) - var/newrpm = ((compressor.gas_contained.temperature) * compressor.gas_contained.total_moles())/4 + var/newrpm = ((compressor.gas_contained.temperature) * compressor.gas_contained.total_moles)/4 newrpm = max(0, newrpm) if(!compressor.starter || newrpm > 1000) compressor.rpmtarget = newrpm - if(compressor.gas_contained.total_moles()>0) - var/oamount = min(compressor.gas_contained.total_moles(), (compressor.rpm+100)/35000*compressor.capacity) + if(compressor.gas_contained.total_moles>0) + var/oamount = min(compressor.gas_contained.total_moles, (compressor.rpm+100)/35000*compressor.capacity) var/datum/gas_mixture/removed = compressor.gas_contained.remove(oamount) outturf.assume_air(removed) diff --git a/code/modules/research/server.dm b/code/modules/research/server.dm index 1c525f22e75..604a31c5d57 100644 --- a/code/modules/research/server.dm +++ b/code/modules/research/server.dm @@ -75,7 +75,7 @@ var/datum/gas_mixture/env = L.return_air() if(env.temperature < (heat_amt+T0C)) - var/transfer_moles = 0.25 * env.total_moles() + var/transfer_moles = 0.25 * env.total_moles var/datum/gas_mixture/removed = env.remove(transfer_moles) diff --git a/code/unused/heater.dm b/code/unused/heater.dm index 3af7770a066..b735141151e 100644 --- a/code/unused/heater.dm +++ b/code/unused/heater.dm @@ -22,7 +22,7 @@ else T = null if (src.h_status) - var/t1 = src.gas.total_moles() + var/t1 = src.gas.total_moles if ((t1 > 0 && src.gas.temperature < (src.h_tar+T0C))) var/increase = src.heatrate / t1 var/n_temp = src.gas.temperature + increase @@ -31,7 +31,7 @@ switch(src.t_status) if(1.0) if (src.holding) - var/t1 = src.gas.total_moles() + var/t1 = src.gas.total_moles var/t2 = t1 var/t = src.t_per if (src.t_per > t2) @@ -41,7 +41,7 @@ src.t_status = 3 if(2.0) if (src.holding) - var/t1 = src.gas.total_moles() + var/t1 = src.gas.total_moles var/t2 = src.maximum - t1 var/t = src.t_per if (src.t_per > t2) @@ -97,7 +97,7 @@ ct = text("Release Accept Stopped", src, src) else ct = "Disconnected" - var/dat = text("Canister Valves
\nContains/Capacity [] / []
\nUpper Valve Status: [][]
\n\tM - - - - [] + + + + M
\nHeater Status: [] - []
\n\tTrg Tmp: - - - [] + + +
\n
\nPipe Valve Status: []
\n\tM - - - - [] + + + + M
\n
\nClose
\n
", src.gas.total_moles(), src.maximum, tt, (src.holding ? text("
Tank ([])", src, src.holding.gas.total_moles()) : null), src, num2text(1000000.0, 7), src, src, src, src, src.t_per, src, src, src, src, src, num2text(1000000.0, 7), ht, (src.gas.total_moles() ? (src.gas.temperature-T0C) : 20), src, src, src, src.h_tar, src, src, src, ct, src, num2text(1000000.0, 7), src, src, src, src, src.c_per, src, src, src, src, src, num2text(1000000.0, 7), user) + var/dat = text("Canister Valves
\nContains/Capacity [] / []
\nUpper Valve Status: [][]
\n\tM - - - - [] + + + + M
\nHeater Status: [] - []
\n\tTrg Tmp: - - - [] + + +
\n
\nPipe Valve Status: []
\n\tM - - - - [] + + + + M
\n
\nClose
\n
", src.gas.total_moles, src.maximum, tt, (src.holding ? text("
Tank ([])", src, src.holding.gas.total_moles) : null), src, num2text(1000000.0, 7), src, src, src, src, src.t_per, src, src, src, src, src, num2text(1000000.0, 7), ht, (src.gas.total_moles ? (src.gas.temperature-T0C) : 20), src, src, src, src.h_tar, src, src, src, ct, src, num2text(1000000.0, 7), src, src, src, src, src.c_per, src, src, src, src, src, num2text(1000000.0, 7), user) user << browse(dat, "window=canister;size=600x300") onclose(user, "canister") return */ //TODO: FIX diff --git a/code/unused/pipe.dm b/code/unused/pipe.dm index 29de0c78cd3..ce4e9a10d04 100644 --- a/code/unused/pipe.dm +++ b/code/unused/pipe.dm @@ -59,17 +59,17 @@ var/linenums = 0 /* /obj/machinery/pipeline/get_gas_moles(from) - return gas.total_moles()/capmult + return gas.total_moles/capmult */ /obj/machinery/pipeline/get_gas(from) return gas /obj/machinery/pipeline/gas_flow() - //if(suffix == "d" && Debug) world.log << "PLF1 [gas.total_moles()] ~ [ngas.total_moles()]" + //if(suffix == "d" && Debug) world.log << "PLF1 [gas.total_moles] ~ [ngas.total_moles]" gas.copy_from(ngas) - //if(suffix == "d" && Debug) world.log << "PLF2 [gas.total_moles()] ~ [ngas.total_moles()]" + //if(suffix == "d" && Debug) world.log << "PLF2 [gas.total_moles] ~ [ngas.total_moles]" /obj/machinery/pipeline/process() /* @@ -81,7 +81,7 @@ var/linenums = 0 // var/dbg = (suffix == "d") && Debug - //if(dbg) world.log << "PLP1 [gas.total_moles()] ~ [ngas.total_moles()]" + //if(dbg) world.log << "PLP1 [gas.total_moles] ~ [ngas.total_moles()]" if(!numnodes) return //dividing by zero is bad okay? From 502c66664c61ac2464bd40e77bf4aaf544ee78ed Mon Sep 17 00:00:00 2001 From: SkyMarshal Date: Tue, 1 May 2012 14:29:42 -0700 Subject: [PATCH 2/4] Some more work on FEA, WIP FEA/ZAS work, does not effect the game currently. --- baystation12.dme | 4 + code/ATMOSPHERICS/pipes.dm | 16 - code/FEA/DEBUG_REMOVE_BEFORE_RELEASE.dm | 7 +- code/FEA/FEA_ZAS.dm | 57 ++ code/FEA/FEA_ZAS_Airflow.dm | 451 +++++++++++++ code/FEA/FEA_airgroup.dm | 174 ++--- code/FEA/FEA_fire.dm | 16 +- code/FEA/FEA_gas_mixture.dm | 78 ++- code/FEA/FEA_system.dm | 210 ++---- code/FEA/FEA_turf_tile.dm | 44 +- code/FEA/FEA_variables.dm | 631 ++++++++++++++++++ .../Cael_Aislinn/Supermatter/SuperMatter.dm | 12 +- .../Ported/ZeroPoint/SuperMatter.dm | 120 ---- code/game/machinery/atmoalter/canister.dm | 7 +- code/game/machinery/atmoalter/zvent.dm | 6 +- code/game/magic/library.dm | 6 +- code/game/master_controller.dm | 2 +- code/game/objects/tank.dm | 1 - code/game/objects/tanks/emergency.dm | 7 +- code/game/objects/tanks/jetpack.dm | 6 +- code/game/objects/tanks/oxygen.dm | 2 +- code/setup.dm | 4 +- 22 files changed, 1373 insertions(+), 488 deletions(-) create mode 100644 code/FEA/FEA_ZAS.dm create mode 100644 code/FEA/FEA_ZAS_Airflow.dm create mode 100644 code/FEA/FEA_variables.dm delete mode 100644 code/WorkInProgress/Ported/ZeroPoint/SuperMatter.dm diff --git a/baystation12.dme b/baystation12.dme index d007fb1cced..47ceda83761 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -356,12 +356,16 @@ #include "code\defines\sd_procs\constants.dm" #include "code\defines\sd_procs\direction.dm" #include "code\defines\sd_procs\math.dm" +#include "code\FEA\DEBUG_REMOVE_BEFORE_RELEASE.dm" #include "code\FEA\FEA_airgroup.dm" #include "code\FEA\FEA_fire.dm" #include "code\FEA\FEA_gas_mixture.dm" #include "code\FEA\FEA_group_helpers.dm" #include "code\FEA\FEA_system.dm" #include "code\FEA\FEA_turf_tile.dm" +#include "code\FEA\FEA_variables.dm" +#include "code\FEA\FEA_ZAS.dm" +#include "code\FEA\FEA_ZAS_Airflow.dm" #include "code\game\algorithm.dm" #include "code\game\atom_procs.dm" #include "code\game\cellautomata.dm" diff --git a/code/ATMOSPHERICS/pipes.dm b/code/ATMOSPHERICS/pipes.dm index 74e76392002..577bf562dce 100644 --- a/code/ATMOSPHERICS/pipes.dm +++ b/code/ATMOSPHERICS/pipes.dm @@ -464,22 +464,6 @@ obj/machinery/atmospherics/pipe ..() - oxygen_agent_b - icon = 'red_orange_pipe_tank.dmi' - name = "High Capacity Pressure Tank (Oxygen + Plasma)" - - New() - air_temporary = new - air_temporary.volume = volume - air_temporary.temperature = T0C - - var/datum/gas/oxygen_agent_b/trace_gas = new - trace_gas.moles = (160*ONE_ATMOSPHERE)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature) - - air_temporary.trace_gases += trace_gas - - ..() - oxygen icon = 'blue_pipe_tank.dmi' name = "High Capacity Pressure Tank (Oxygen)" diff --git a/code/FEA/DEBUG_REMOVE_BEFORE_RELEASE.dm b/code/FEA/DEBUG_REMOVE_BEFORE_RELEASE.dm index c3b549b10c3..8942a16bb28 100644 --- a/code/FEA/DEBUG_REMOVE_BEFORE_RELEASE.dm +++ b/code/FEA/DEBUG_REMOVE_BEFORE_RELEASE.dm @@ -116,7 +116,7 @@ obj/machinery/portable_atmospherics/canister valve_open = 1 release_pressure = 1000 - +/* obj/machinery/atmospherics unary heat_reservoir @@ -352,6 +352,7 @@ obj/machinery/atmospherics usr << "[x],[y] is in a pipeline with [parent.members.len] members ([parent.edges.len] edges)! Volume: [parent.air.volume]" usr << "Pressure: [parent.air.return_pressure()], Temperature: [parent.air.temperature]" usr << "[parent.air.oxygen], [parent.air.toxins], [parent.air.nitrogen], [parent.air.carbon_dioxide] .. [parent.alert_pressure]" +*/ mob verb flag_all_pipe_networks() @@ -519,7 +520,7 @@ mob for(var/obj/effect/hotspot/flame in world) usr << "[flame.x],[flame.y]: [flame.temperature]K, [flame.volume] L - [flame.loc:air:temperature]" - process_cycle() +/* process_cycle() set category = "Debug" if(!master_controller) usr << "Cannot find master_controller" @@ -595,7 +596,7 @@ mob if(S.processing) S.icon_state = "individual_on" else - S.icon_state = "individual_off" + S.icon_state = "individual_off"*/ mark_groups() diff --git a/code/FEA/FEA_ZAS.dm b/code/FEA/FEA_ZAS.dm new file mode 100644 index 00000000000..766cbe5fe4e --- /dev/null +++ b/code/FEA/FEA_ZAS.dm @@ -0,0 +1,57 @@ +/* AN EXPLANATION: +This file was added because I felt that the computations for movement +of air over large scales was not adequately done by FEA, and the attempt +to solve this problem, in the form of ZAS (Zone Atmos System), +simplified it too far, in my opinion, creating the effect of a single +opened air canister filling an entire room with a partial mix of that +gas with the pre-existing mix. This was slightly silly, due to large +rooms "flash filling" when you opened a canister, and the fact that the +procedures to recalculate the boundaries of the zones was far from +foolproof, and, indeed, often let air flash though solid bulkheads to +space. + +To solve this, I've both commented the hell out of the existing FEA code, +removed and/or replaced procs with more efficient procs, and added this +file, which contains some procedures for special cases, such as: + 1.) Moving large volumes of air into vacuum/lower pressure environs + (triggers when pressure behind a tile moving air to a lower + pressure exceeds an amount.) + e.g. A room of full air gets opened to a depressurised room + 2.) Dealing with pressure equalization. + (triggers when a large amount of gas is added to a room, it + follows behind the "stormfront" of gas change (Managed by FEA) + and triggers a rapid equalization of gas by utilizing a + psuedo-zone.) + e.g. Opening a tank of oxygen in a low pressure room, and after + spreading by FEA, it equalizes the pressure in the room, instead + instead of slowly flowing out like molasses. + +These procedures trigger when a check is made against the pressure changes +and situations occuring to the airgroup (if it is venting at high pressure, +airgroups will rejoin even if broken to ZAS process) will call these +specialized procs to help properly deal with these situation. +--SkyMarshal, May 2012*/ +/* WIP + + if(space_tiles) + for(var/T in space_tiles) + if(!istype(T,/turf/space)) space_tiles -= T + total_space += length(space_tiles) + if(length(space_tiles)) + space = space_tiles[1] + + if(total_space && space) + var/old_pressure = air.return_pressure() + air.temperature_mimic(space,OPEN_HEAT_TRANSFER_COEFFICIENT,total_space) + air.remove(MOLES_CELLSTANDARD * (air.group_multiplier/40) * total_space) + var/p_diff = old_pressure - air.return_pressure() + if(p_diff > vsc.AF_TINY_MOVEMENT_THRESHOLD) AirflowSpace(src,p_diff) + + air.graphic_archived = air.graphic + + air.temperature = max(TCMB,air.temperature) + + var/p_diff = (air.return_pressure()-Z.air.return_pressure())*connected_zones[Z]*(vsc.zone_share_percent/100) + if(p_diff > vsc.AF_TINY_MOVEMENT_THRESHOLD) Airflow(src,Z,p_diff) + air.share_ratio(Z.air,connected_zones[Z]*(vsc.zone_share_percent/100)) + */ \ No newline at end of file diff --git a/code/FEA/FEA_ZAS_Airflow.dm b/code/FEA/FEA_ZAS_Airflow.dm new file mode 100644 index 00000000000..5fc42651c87 --- /dev/null +++ b/code/FEA/FEA_ZAS_Airflow.dm @@ -0,0 +1,451 @@ +/* + +CONTAINS: +All AirflowX() procs, all Variable Setting Controls for airflow, save/load variable tweaks for airflow. + +VARIABLES: + +atom/movable/airflow_dest + The destination turf of a flying object. + +atom/movable/airflow_speed + The speed (1-15) at which a flying object is traveling to airflow_dest. Decays over time. + + +OVERLOADABLE PROCS: + +mob/airflow_stun() + Contains checks for and results of being stunned by airflow. + Called when airflow quantities exceed AF_HUMAN_STUN_THRESHOLD. + RETURNS: Null + +atom/movable/check_airflow_movable(n) + Contains checks for moving any object due to airflow. + n is the percent of 1 Atmosphere that is flowing. + RETURNS: 1 if the object moves under the air conditions, 0 if it stays put. + +atom/movable/airflow_hit(atom/A) + Contains results of hitting a solid object (A) due to airflow. + A is the dense object hit. + Use airflow_speed to determine how fast the projectile was going. + + +AUTOMATIC PROCS: + +Airflow(datum/air_group/A, datum/air_group/B, n, vae/list/turf/simulated/target) + Causes objects to fly along a pressure gradient. + Called by airflow calculations finding a high pressure gradient. A and B are two adjacent airgroups. + n is the pressure difference between them. + targets is a list of turfs between them. + +AirflowSpace(zone/A) + Causes objects to fly into space. + Called by airflow to space. A is a airgroup connected to space. + +atom/movable/GotoAirflowDest(n) +atom/movable/RepelAirflowDest(n) + Called by main airflow procs to cause the object to fly to or away from destination at speed n. + Probably shouldn't call this directly unless you know what you're + doing and have set airflow_dest. airflow_hit() will be called if the object collides with an obstacle. + +*/ + +mob/proc/airflow_stun() + //Purpose: AIRFLOW + //Called by: AIRFLOW + //Inputs: Hate + //Outputs: Sadness + + if(weakened <= 0) + src << pickweight("\red The sudden rush of air knocks you over!" = 5, "\red You get dragged off your feet by a rush of air!" = 5, "\red FUCKING AIRFLOW!" = 1) + weakened = max(weakened,5) + +mob/living/silicon/airflow_stun() + return + +mob/living/carbon/metroid/airflow_stun() + return + +mob/living/carbon/human/airflow_stun() + if(buckled) return 0 + if(wear_suit) + if(wear_suit.flags & SUITSPACE) return 0 + if(shoes) + if(shoes.flags & NOSLIP) return 0 + if(weakened <= 0) + src << pickweight("\red The sudden rush of air knocks you over!" = 5, "\red You get dragged off your feet by a rush of air!" = 5, "\red FUCKING AIRFLOW!" = 1) + weakened = max(weakened,2) + +atom/movable/proc/check_airflow_movable(n) + //Purpose: Determining if src is movable by airflow. + //Called by: AIRFLOW + //Inputs: Movement force + //Outputs: Boolean of capability to be moved. + + if(anchored && !ismob(src)) return 0 + + if(!istype(src,/obj/item) && n < air_master.AF_DENSE_MOVEMENT_THRESHOLD) return 0 + if(ismob(src) && n < air_master.AF_MOB_MOVEMENT_THRESHOLD) return 0 + + return 1 + +mob/dead/observer/check_airflow_movable() + return 0 + +mob/living/silicon/check_airflow_movable() + return 0 + + +obj/item/check_airflow_movable(n) + . = ..() + switch(w_class) + if(2) + if(n < air_master.AF_SMALL_MOVEMENT_THRESHOLD) return 0 + if(3) + if(n < air_master.AF_NORMAL_MOVEMENT_THRESHOLD) return 0 + if(4,5) + if(n < air_master.AF_LARGE_MOVEMENT_THRESHOLD) return 0 + +proc/Airflow(datum/air_group/A,datum/air_group/B,n,var/list/turf/simulated/target) + //Purpose: AIRFLOW between two airgroups. + //Called by: AIRFLOW + //Inputs: Air group venting, Air group receiving, force of airflow, midpoint turf(s) + //Outputs: None. + + //Now n is a percent of one atm. + n = round((n/air_master.AF_PERCENT_OF)*100,0.1) + + //Don't go any further if n is lower than the lowest value needed for airflow. + if(abs(n) < air_master.AF_TINY_MOVEMENT_THRESHOLD) + return + + if(!target || !target.len) + return + + //Get lists of things that can be thrown across the room for each zone. + var/list/pplz = A.movables() + var/list/otherpplz = B.movables() + + for(var/atom/movable/M in pplz) + + //Check for knocking people over + if(ismob(M) && n > air_master.AF_HUMAN_STUN_THRESHOLD) + if(M:nodamage) continue + M:airflow_stun() + + if(M.check_airflow_movable(n)) + + //Check for things that are in range of the midpoint turfs. + var/fail = 1 + for(var/turf/simulated/T in target) + if(M in range(T)) + fail = 0 + break + if(fail) + continue + + //If they're already being tossed, don't do it again. + if(!M.airflow_speed) + + M.airflow_dest = pick(target) //Pick a random midpoint to fly towards. + + spawn M.GotoAirflowDest(abs(n) * (air_master.AF_SPEED_MULTIPLIER/10)) + //Send the object flying at a speed determined by n and AF_SPEED_MULTIPLIER. + + //Do it again for the stuff in the other zone, making it fly away. + for(var/atom/movable/M in otherpplz) + + if(ismob(M) && abs(n) > air_master.AF_HUMAN_STUN_THRESHOLD) + if(M:nodamage) continue + M:airflow_stun() + + if(M.check_airflow_movable(abs(n))) + + var/fail = 1 + for(var/turf/simulated/T in target) + if(M in range(T)) + fail = 0 + break + if(fail) + continue + + if(M && !M.airflow_speed) + + M.airflow_dest = pick(target) + + spawn M.RepelAirflowDest(abs(n) * (air_master.AF_SPEED_MULTIPLIER/10)) + +proc/AirflowSpace(datum/air_group/A) + //Purpose: AIRFLOW between an airgroup and spess. + //Called by: AIRFLOW + //Inputs: Air group venting into space. + //Outputs: None. + // The space version of the Airflow(A,B,n) proc. + + var/n = A.air.total_moles*air_master.AF_SPACE_MULTIPLIER + //Here, n is determined by the space multiplier constant and the zone's air. + + n = round((n/air_master.AF_PERCENT_OF)*100,0.1) + + if(n < air_master.AF_TINY_MOVEMENT_THRESHOLD) return + + var/list/connected_turfs = A.space_borders //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. + + for(var/atom/movable/M in pplz) + + if(ismob(M) && n > air_master.AF_HUMAN_STUN_THRESHOLD) + if(M:nodamage) continue + M:airflow_stun() + + if(M.check_airflow_movable(n)) + + var/fail = 1 + for(var/turf/U in connected_turfs) + if(M in range(U)) fail = 0 + if(fail) continue + + if(!M.airflow_speed) + M.airflow_dest = pick(connected_turfs) + spawn + if(M) M.GotoAirflowDest(n * (air_master.AF_SPEED_MULTIPLIER/10)) + //Sometimes shit breaks, and M isn't there after the spawn. + +/atom/movable + var/turf/airflow_dest + var/airflow_speed = 0 + var/airflow_time = 0 + + proc/GotoAirflowDest(n) + //Purpose: Moving src between it's current position and where air is dragging them. + //Called by: AIRFLOW + //Inputs: Force. + //Outputs: None. + + if(!airflow_dest) return + if(airflow_speed < 0) return + if(airflow_speed) + airflow_speed = n + return + if(airflow_dest == loc) + step_away(src,loc) + if(ismob(src)) + if(src:nodamage) return + if(istype(src, /mob/living/carbon/human)) + if(istype(src, /mob/living/carbon/human)) + if(src:buckled) return + if(src:wear_suit) + if(src:wear_suit.flags & SUITSPACE) return + if(src:shoes) + if(src:shoes.type == /obj/item/clothing/shoes/magboots && src:shoes.flags & NOSLIP) return + src << "\red You are sucked away by airflow!" + + airflow_speed = min(round(n),9) + airflow_speed /= get_dist(src,airflow_dest) //The further away you are, the less you get dragged. + var + xo = airflow_dest.x - src.x + yo = airflow_dest.y - src.y + od = 0 + airflow_dest = null + if(!density) + density = 1 + od = 1 //It wasn't dense, but it is considered it for when being moved by airflow. + //Main loop to AIRFLOW + while(airflow_speed > 0) + if(airflow_speed <= 0) return + airflow_speed = min(airflow_speed,15) + airflow_speed -= air_master.AF_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 + step_towards(src, src.airflow_dest) + if(ismob(src) && src:client) src:client:move_delay = world.time + 10 + airflow_dest = null + //You cannot be tossed around by airflow more than once ever 1.5(times tick_multiplier) seconds) + airflow_speed = -1 + spawn(150 * tick_multiplier) airflow_speed = 0 + //Reset density. + if(od) + density = 0 + + proc/RepelAirflowDest(n) + //Purpose: Moving src between it's current position and where air is pushing them. + //Called by: AIRFLOW + //Inputs: Force. + //Outputs: None. + + if(!airflow_dest) return + if(airflow_speed < 0) return + if(airflow_speed) + airflow_speed = n + return + if(airflow_dest == loc) + step_away(src,loc) + if(ismob(src)) + if(src:nodamage) return + if(istype(src, /mob/living/carbon/human)) + if(istype(src, /mob/living/carbon/human)) + if(src:buckled) return + if(src:wear_suit) + if(src:wear_suit.flags & SUITSPACE) return + if(src:shoes) + if(src:shoes.type == /obj/item/clothing/shoes/magboots) return + src << "\red You are pushed away by airflow!" + airflow_speed = min(round(n),9) + airflow_speed /= get_dist(src,airflow_dest) //The further away you are, the less you get dragged. + 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 -= air_master.AF_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 + step_towards(src, src.airflow_dest) + if(ismob(src) && src:client) src:client:move_delay = world.time + 10 + airflow_dest = null + airflow_speed = -1 + spawn(150 * tick_multiplier) airflow_speed = 0 + if(od) + density = 0 + + Bump(atom/A) + if(airflow_speed > 0 && airflow_dest) + airflow_hit(A) + else + airflow_speed = 0 + . = ..() + +atom/movable/proc/airflow_hit(atom/A) + //Purpose: Managing impacts between objects whirled around by airflow. + //Called by: AIRFLOW + //Inputs: Object to impact. + //Outputs: None. + + airflow_speed = -1 + spawn(50 * tick_multiplier) airflow_speed = 0 + airflow_dest = null + +mob/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, "smash.ogg", 25, 1, -1) + . = ..() + +obj/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, "smash.ogg", 25, 1, -1) + . = ..() + +obj/item/airflow_hit(atom/A) + airflow_speed = -1 + spawn(50 * tick_multiplier) airflow_speed = 0 + airflow_dest = null + +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) + 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 * air_master.AF_DAMAGE_MULTIPLIER + for(var/organ in src:organs) + var/datum/organ/external/temp = src:organs["[organ]"] + if (istype(temp, /datum/organ/external)) + switch(temp.name) + if("head") + temp.take_damage(b_loss * 0.2, 0) + if("chest") + temp.take_damage(b_loss * 0.4, 0) + if("diaper") + temp.take_damage(b_loss * 0.1, 0) + spawn UpdateDamageIcon() + if(airflow_speed > 10) + paralysis += round(airflow_speed * air_master.AF_STUN_MULTIPLIER) + stunned = max(stunned,paralysis + 3) + else + stunned += round(airflow_speed * air_master.AF_STUN_MULTIPLIER/2) + . = ..() + +/datum/air_group/proc/movables() + //Purpose: Returns everything movable. + //Called by: AIRFLOW + //Inputs: Possible objects to move. + //Outputs: None. + + . = list() + for(var/turf/T in members) + for(var/atom/A in T) + . += A + +proc/Get_Dir(atom/S,atom/T) //Shamelessly stolen from AJX.AdvancedGetDir + var/GDist=get_dist(S,T) + var/GDir=get_dir(S,T) + if(GDist<=3) + if(GDist==0) return 0 + if(GDist==1) + return GDir + + + var/X1=S.x*10 + var/X2=T.x*10 + var/Y1=S.y*10 + var/Y2=T.y*10 + var/Ref + if(GDir==NORTHEAST) + Ref=(X2/X1)*Y1 + if(Ref-1>Y2) .=EAST + else if(Ref+1Y2) .=WEST + else if(Ref+1Y2) .=SOUTH + else if(Ref+1Y2) .=SOUTH + else if(Ref+1> air_master + del F + world.log << "TWEAKS: Airflow, Plasma and Damage settings loaded." \ No newline at end of file diff --git a/code/FEA/FEA_airgroup.dm b/code/FEA/FEA_airgroup.dm index c31ab6f503a..c92c3838d14 100644 --- a/code/FEA/FEA_airgroup.dm +++ b/code/FEA/FEA_airgroup.dm @@ -10,29 +10,8 @@ datum // to be rolled into the updating step //optimization vars - var/tmp/next_check = 0 //number of ticks before this group updates - var/tmp/check_delay = 10 //number of ticks between updates, starts fairly high to get boring groups out of the way - - proc - archive() - - members() - //Returns the members of the group - - check_regroup() - //If individually processing tiles, checks all member tiles to see if they are close enough - // that the group may resume group processing - //Warning: Do not call, called by air_master.process() - - process_group() - suspend_group_processing() - update_group_from_tiles() - //Copy group air information to individual tile air - //Used right before turning on group processing - - update_tiles_from_group() - //Copy group air information to individual tile air - //Used right before turning off group processing +// var/tmp/next_check = 0 //number of ticks before this group updates +// var/tmp/check_delay = 10 //number of ticks between updates, starts fairly high to get boring groups out of the way var/list/borders //Tiles that connect this group to other groups/individual tiles var/list/members //All tiles in this group @@ -40,13 +19,21 @@ datum var/list/space_borders var/length_space_border = 0 - suspend_group_processing() + proc/suspend_group_processing() + //Purpose: Suspends processing of the group, breaks it into individual tiles. + //Called by: Any check where the airgroup is determined to break. + //Inputs: None. + //Outputs: None. + group_processing = 0 update_tiles_from_group() - check_delay=0 - next_check=0 - update_group_from_tiles() + proc/update_group_from_tiles() + //Purpose: Regathers the tiles of the group into the airgroup, reverses update_tiles_from_group() + //Called by: Any check where the airgroup is determined to reconnect. + //Inputs: None. + //Outputs: None. + var/sample_member = pick(members) var/datum/gas_mixture/sample_air = sample_member:air @@ -55,20 +42,30 @@ datum return 1 - update_tiles_from_group() + proc/update_tiles_from_group() + //Purpose: Breaks the group into individual tiles. + //Called by: Any check where the airgroup is determined to break. + //Inputs: None. + //Outputs: None. + for(var/member in members) member:air.copy_from(air) - if (istype(member,/turf/simulated)) - var/turf/simulated/turfmem=member - turfmem.reset_delay() - archive() + proc/archive() + //Purpose: Archives the air for optimization. + //Called by: ? + //Inputs: None. + //Outputs: None. + air.archive() archived_cycle = air_master.current_cycle - check_regroup() + proc/check_regroup() //Purpose: Checks to see if group processing should be turned back on - //Returns: group_processing + //Called by: Any time an airgroup is checked to reform + //Inputs: None. + //Outputs: if the group is processing or not, boolean + if(group_processing) return 1 @@ -85,15 +82,14 @@ datum return 1 - turf/process_group() + proc/process_group() + //Purpose: Processes group atmos + //Called by: Atmos Ticker. + //Inputs: None. + //Outputs: None. + current_cycle = air_master.current_cycle if(group_processing) //See if processing this group as a group - //check if we're skipping this tick - if (next_check > 0) - next_check-- - return 1 - next_check += check_delay + rand(0,check_delay/2) - check_delay++ var/turf/simulated/list/border_individual = list() var/datum/air_group/list/border_group = list() @@ -108,22 +104,9 @@ datum //But only if another group didn't store it for us for(var/turf/simulated/border_tile in src.borders) - //var/obj/movable/floor/movable_on_me = locate(/obj/movable/floor) in border_tile for(var/direction in cardinal) //Go through all border tiles and get bordering groups and individuals if(border_tile.group_border&direction) - var/turf/simulated/enemy_tile = get_step(border_tile, direction) //Add found tile to appropriate category - //var/obj/movable/floor/movable_on_enemy - //if(!movable_on_me) - // movable_on_enemy = locate(/obj/movable/floor) in enemy_tile - /*if(movable_on_enemy) //guaranteed !movable_on_me if this is set - if(movable_on_enemy.parent && movable_on_enemy.parent.group_processing) - border_group += movable_on_enemy.parent - enemies += movable_on_enemy - self_group_borders += border_tile - else - border_individual += movable_on_enemy - self_tile_borders += border_tile - else*/ + var/turf/simulated/enemy_tile = get_step(border_tile, direction) if(istype(enemy_tile) && enemy_tile.parent && enemy_tile.parent.group_processing) border_group += enemy_tile.parent enemies += enemy_tile @@ -233,83 +216,4 @@ datum member.hotspot_expose(air.temperature, CELL_VOLUME) member.consider_superconductivity(starting=1) - air.react() - - object/process_group() - current_cycle = air_master.current_cycle - - if(group_processing) //See if processing this group as a group - - var/turf/simulated/list/border_individual = list() - var/datum/air_group/list/border_group = list() - - var/turf/simulated/list/enemies = list() //used to send the appropriate border tile of a group to the group proc - var/enemy_index = 1 - - if(archived_cycle < air_master.current_cycle) - archive() - //Archive air data for use in calculations - //But only if another group didn't store it for us -/* - for(var/obj/movable/floor/border_tile in src.borders) - for(var/direction in list(NORTH,SOUTH,EAST,WEST)) //Go through all border tiles and get bordering groups and individuals - if(border_tile.group_border&direction) - var/turf/simulated/enemy_tile = get_step(border_tile, direction) //Add found tile to appropriate category - var/obj/movable/floor/movable_on_enemy = locate(/obj/movable/floor) in enemy_tile - if(movable_on_enemy) - if(movable_on_enemy.parent && movable_on_enemy.parent.group_processing) - border_group += movable_on_enemy.parent - enemies += movable_on_enemy - enemy_index++ - else - border_individual += movable_on_enemy - - else - if(istype(enemy_tile) && enemy_tile.parent && enemy_tile.parent.group_processing) - border_group += enemy_tile.parent - enemies += enemy_tile - enemy_index++ - else - border_individual += enemy_tile -*/ - enemy_index = 1 - var/abort_group = 0 - for(var/datum/air_group/AG in border_group) - if(AG.archived_cycle < archived_cycle) //archive other groups information if it has not been archived yet this cycle - AG.archive() - if(AG.current_cycle < current_cycle) - //This if statement makes sure two groups only process their individual connections once! - //Without it, each connection would be processed a second time as the second group is evaluated - - var/result = air.check_gas_mixture(AG.air) - if(result == 1) - air.share(AG.air) - else if(result == -1) - AG.suspend_group_processing() - var/turf/simulated/floor/enemy_border = enemies[enemy_index] - air.share(enemy_border.air) - else - abort_group = 0 - break - enemy_index++ - - if(!abort_group) - for(var/enemy_tile in border_individual) - if(istype(enemy_tile, /turf/simulated)) - if(enemy_tile:archived_cycle < archived_cycle) //archive tile information if not already done - enemy_tile:archive() - if(enemy_tile:current_cycle < current_cycle) - if(air.check_gas_mixture(enemy_tile:air)) - air.share(enemy_tile:air) - else - abort_group = 1 - break - else - if(air.check_turf(enemy_tile)) - air.mimic(enemy_tile) - else - abort_group = 1 - break - - if(abort_group) - suspend_group_processing() \ No newline at end of file + air.react() \ No newline at end of file diff --git a/code/FEA/FEA_fire.dm b/code/FEA/FEA_fire.dm index 675b70441fb..14fd727dd92 100644 --- a/code/FEA/FEA_fire.dm +++ b/code/FEA/FEA_fire.dm @@ -1,10 +1,18 @@ atom - proc - temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume) - return null + proc/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume) + //Purpose: Managing temperature exposure. + //Called by: Atmos + //Inputs: Airmix, temperature, volume. + //Outputs: None. + + return null turf proc/hotspot_expose(exposed_temperature, exposed_volume, soh = 0) + //Purpose: Making the equivilent of a spark. + //Called by: Atmos. Anything that might light a fire. + //Inputs: Temperature, Volume, ? + //Outputs: If it is igniting or not. simulated hotspot_expose(exposed_temperature, exposed_volume, soh) @@ -40,7 +48,7 @@ turf //remove just_spawned protection if no longer processing this cell //start processing quickly if we aren't already - reset_delay() +// reset_delay() return igniting diff --git a/code/FEA/FEA_gas_mixture.dm b/code/FEA/FEA_gas_mixture.dm index 5ceb602436a..dca70cfb578 100644 --- a/code/FEA/FEA_gas_mixture.dm +++ b/code/FEA/FEA_gas_mixture.dm @@ -12,6 +12,7 @@ What are the archived variables for? #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. @@ -57,6 +58,31 @@ datum graphic_archived fuel_burnt = 0 + +//FOR THE LOVE OF GOD PLEASE USE THIS PROC +//Call it with negative numbers to remove gases. + + proc/adjustGases(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 + /////////////////////////////// //PV=nRT - related procedures// /////////////////////////////// @@ -441,10 +467,16 @@ datum // then -1 if sharer-check failed (sharing airgroup breaks?) // then 1 if both checks pass (share succesful?) - var/delta_oxygen = (oxygen_archived - sharer.oxygen_archived)/5 - var/delta_carbon_dioxide = (carbon_dioxide_archived - sharer.carbon_dioxide_archived)/5 - var/delta_nitrogen = (nitrogen_archived - sharer.nitrogen_archived)/5 - var/delta_toxins = (toxins_archived - sharer.toxins_archived)/5 + var/pressure = 1 + if(!return_pressure() || !sharer.return_pressure()) + pressure = 3 + else if(pressure < 0) + pressure = (sharer.return_pressure() / return_pressure()) + pressure = max(min(pressure,3),1) //Lets cap this. + var/delta_oxygen = max(QUANTIZE(oxygen_archived - sharer.oxygen_archived) * pressure/TRANSFER_FRACTION,oxygen) + var/delta_carbon_dioxide = max(QUANTIZE(carbon_dioxide_archived - sharer.carbon_dioxide_archived) * pressure/TRANSFER_FRACTION,carbon_dioxide) + var/delta_nitrogen = max(QUANTIZE(nitrogen_archived - sharer.nitrogen_archived) * pressure/TRANSFER_FRACTION,nitrogen) + var/delta_toxins = max(QUANTIZE(toxins_archived - sharer.toxins_archived) * pressure/TRANSFER_FRACTION,toxins) var/delta_temperature = (temperature_archived - sharer.temperature_archived) @@ -497,10 +529,10 @@ datum //Inputs: Unsimulated turf //Outputs: 1 if safe to mimic, 0 if needs to break airgroup. - var/delta_oxygen = (oxygen_archived - model.oxygen)/5 - var/delta_carbon_dioxide = (carbon_dioxide_archived - model.carbon_dioxide)/5 - var/delta_nitrogen = (nitrogen_archived - model.nitrogen)/5 - var/delta_toxins = (toxins_archived - model.toxins)/5 + 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) @@ -527,10 +559,16 @@ datum //Outputs: Amount of gas exchanged (Negative if lost air, positive if gained.) if(!sharer) return 0 - var/delta_oxygen = QUANTIZE(oxygen_archived - sharer.oxygen_archived)/5 - var/delta_carbon_dioxide = QUANTIZE(carbon_dioxide_archived - sharer.carbon_dioxide_archived)/5 - var/delta_nitrogen = QUANTIZE(nitrogen_archived - sharer.nitrogen_archived)/5 - var/delta_toxins = QUANTIZE(toxins_archived - sharer.toxins_archived)/5 + var/pressure = 1 + if(!return_pressure() || !sharer.return_pressure()) + pressure = 3 + else if(pressure < 0) + pressure = (sharer.return_pressure() / return_pressure()) + pressure = max(min(pressure,3),1) //Lets cap this. + var/delta_oxygen = max(QUANTIZE(oxygen_archived - sharer.oxygen_archived) * pressure/TRANSFER_FRACTION,oxygen) + var/delta_carbon_dioxide = max(QUANTIZE(carbon_dioxide_archived - sharer.carbon_dioxide_archived) * pressure/TRANSFER_FRACTION,carbon_dioxide) + var/delta_nitrogen = max(QUANTIZE(nitrogen_archived - sharer.nitrogen_archived) * pressure/TRANSFER_FRACTION,nitrogen) + var/delta_toxins = max(QUANTIZE(toxins_archived - sharer.toxins_archived) * pressure/TRANSFER_FRACTION,toxins) var/delta_temperature = (temperature_archived - sharer.temperature_archived) @@ -598,12 +636,12 @@ datum var/delta = 0 if(corresponding) - delta = QUANTIZE(trace_gas.moles_archived - corresponding.moles_archived)/5 + delta = max(QUANTIZE(trace_gas.moles_archived - corresponding.moles_archived)*pressure/TRANSFER_FRACTION,trace_gas.moles) else corresponding = new trace_gas.type() sharer.trace_gases += corresponding - delta = trace_gas.moles_archived/5 + delta = max(trace_gas.moles_archived*pressure/TRANSFER_FRACTION,trace_gas.moles) trace_gas.moles -= delta/group_multiplier corresponding.moles += delta/sharer.group_multiplier @@ -632,7 +670,7 @@ datum corresponding = new trace_gas.type() trace_gases += corresponding - delta = trace_gas.moles_archived/5 + delta = max(trace_gas.moles_archived*pressure/TRANSFER_FRACTION,trace_gas.moles) trace_gas.moles -= delta/sharer.group_multiplier corresponding.moles += delta/group_multiplier @@ -673,10 +711,10 @@ datum //Inputs: Unsimulated turf, Multiplier for gas transfer (optional) //Outputs: Amount of gas exchanged - var/delta_oxygen = QUANTIZE(oxygen_archived - model.oxygen)/5 - var/delta_carbon_dioxide = QUANTIZE(carbon_dioxide_archived - model.carbon_dioxide)/5 - var/delta_nitrogen = QUANTIZE(nitrogen_archived - model.nitrogen)/5 - var/delta_toxins = QUANTIZE(toxins_archived - model.toxins)/5 + 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) @@ -721,7 +759,7 @@ datum for(var/datum/gas/trace_gas in trace_gases) var/delta = 0 - delta = trace_gas.moles_archived/5 + delta = trace_gas.moles_archived/TRANSFER_FRACTION if(border_multiplier) trace_gas.moles -= delta*border_multiplier/group_multiplier diff --git a/code/FEA/FEA_system.dm b/code/FEA/FEA_system.dm index 1f63fcdb67b..fb7e87ac99c 100644 --- a/code/FEA/FEA_system.dm +++ b/code/FEA/FEA_system.dm @@ -56,6 +56,11 @@ Important Procedures var/kill_air = 0 atom/proc/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) + //Purpose: Determines if the object (or airflow) can pass this atom. + //Called by: Movement, airflow. + //Inputs: The moving atom (optional), target turf, "height" and air group + //Outputs: Boolean if can pass. + return (!density || !height || air_group) turf @@ -97,41 +102,12 @@ datum var/list/turf/simulated/groups_to_rebuild = list() var/current_cycle = 0 + var/update_delay = 5 //How long between check should it try to process atmos again. - proc - setup() - //Call this at the start to setup air groups geometry - //Warning: Very processor intensive but only must be done once per round - assemble_group_turf(turf/simulated/base) - //Call this to try to construct a group starting from base and merging with neighboring unparented tiles - //Expands the group until all valid borders explored - -// assemble_group_object(obj/movable/floor/base) - - process() +/* process() //Call this to process air movements for a cycle - process_groups() - //Used by process() - //Warning: Do not call this - - process_singletons() - //Used by process() - //Warning: Do not call this - - process_high_pressure_delta() - //Used by process() - //Warning: Do not call this - - process_super_conductivity() - //Used by process() - //Warning: Do not call this - - process_update_tiles() - //Used by process() - //Warning: Do not call this - process_rebuild_select_groups() //Used by process() //Warning: Do not call this @@ -139,12 +115,16 @@ datum 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 + */ - add_singleton(turf/simulated/T) - if(!active_singletons.Find(T)) - active_singletons += T - setup() + 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 + //Inputs: None. + //Outputs: None. + set background = 1 world << "\red \b Processing Geometry..." sleep(-1) @@ -158,16 +138,16 @@ datum if(S.z > 4) // Skipping asteroids -- TLE continue S.update_air_properties() -/* - for(var/obj/movable/floor/S in world) - if(!S.parent) - assemble_group_object(S) - for(var/obj/movable/floor/S in world) //Update all pathing and border information as well - S.update_air_properties() -*/ - world << "\red \b Geometry processed in [(world.timeofday-start_time)/10] seconds!" - assemble_group_turf(turf/simulated/base) + world << "\red \b Geometry processed in [time2text(world.timeofday-start_time, "mm:ss")] minutes!" + spawn start() + + proc/assemble_group_turf(turf/simulated/base) + //Purpose: Call this to try to construct a group starting from base and merging with neighboring unparented tiles + // (Expands the group until all valid borders explored) + //Called by: setup() + //Inputs: turf to flood fill from. + //Outputs: resulting group, or null if no group is formed. var/list/turf/simulated/members = list(base) //Confirmed group members var/list/turf/simulated/possible_members = list(base) //Possible places for group expansion @@ -196,7 +176,7 @@ datum possible_members -= test if(members.len > 1) - var/datum/air_group/turf/group = new + var/datum/air_group/group = new if(possible_borders.len>0) group.borders = possible_borders if(possible_space_borders.len>0) @@ -221,85 +201,56 @@ datum base.update_visuals(base.air) return null -/* - assemble_group_object(obj/movable/floor/base) - var/list/obj/movable/floor/members = list(base) //Confirmed group members - var/list/obj/movable/floor/possible_members = list(base) //Possible places for group expansion - var/list/obj/movable/floor/possible_borders = list() + proc/start() + //Purpose: This is kicked off by the master controller, and controls the processing of all atmosphere. + //Called by: Master controller + //Inputs: None. + //Outputs: None. - while(possible_members.len>0) //Keep expanding, looking for new members - for(var/obj/movable/floor/test in possible_members) - for(var/direction in list(NORTH, SOUTH, EAST, WEST)) - var/turf/T = get_step(test.loc,direction) - if(T && test.loc.CanPass(null, T, null, 1)) - var/obj/movable/floor/O = locate(/obj/movable/floor) in T - if(istype(O) && !O.parent) - if(!members.Find(O)) - possible_members += O - members += O - else - possible_borders -= test - possible_borders += test - possible_members -= test + set background = 1 + while(1) + if(kill_air) + return 1 + current_cycle++ + if(groups_to_rebuild.len > 0) //If there are groups to rebuild, do so. + spawn process_rebuild_select_groups() - if(members.len > 1) - var/datum/air_group/object/group = new - if(possible_borders.len>0) - group.borders = possible_borders + if(tiles_to_update.len > 0) //If there are tiles to update, do so. + for(var/turf/simulated/T in tiles_to_update) + spawn T.update_air_properties() + tiles_to_update = list() - for(var/obj/movable/floor/test in members) - test.parent = group - test.processing = 0 - active_singletons -= test + for(var/datum/air_group/AG in air_groups) //Processing groups + spawn AG.process_group() + for(var/turf/simulated/T in active_singletons) //Processing Singletons + spawn T.process_cell() - group.members = members - air_groups += group + for(var/turf/simulated/hot_potato in active_super_conductivity) //Process superconduction + spawn hot_potato.super_conduct() - group.update_group_from_tiles() //Initialize air group variables - return group - else - base.processing = 0 //singletons at startup are technically unconnected anyway - base.parent = null + if(high_pressure_delta.len) //Process high pressure delta (airflow) + for(var/turf/pressurized in high_pressure_delta) + spawn pressurized.high_pressure_movements() + high_pressure_delta = list() - return null -*/ - process() - if(kill_air) - return 1 - current_cycle++ - if(groups_to_rebuild.len > 0) process_rebuild_select_groups() - if(tiles_to_update.len > 0) process_update_tiles() + if(current_cycle%10==5) //Check for groups of tiles to resume group processing every 10 cycles + for(var/datum/air_group/AG in air_groups) + spawn AG.check_regroup() + sleep(max(5,update_delay*tick_multiplier)) - process_groups() - process_singletons() - - process_super_conductivity() - process_high_pressure_delta() - - if(current_cycle%10==5) //Check for groups of tiles to resume group processing every 10 cycles - for(var/datum/air_group/AG in air_groups) - AG.check_regroup() - - return 1 - - process_update_tiles() - for(var/turf/simulated/T in tiles_to_update) - T.update_air_properties() -/* - for(var/obj/movable/floor/O in tiles_to_update) - O.update_air_properties() -*/ - tiles_to_update.len = 0 - - process_rebuild_select_groups() + proc/process_rebuild_select_groups() + //Purpose: This gets called to recalculate and rebuild group geometry + //Called by: process() + //Inputs: None. + //Outputs: None. var/turf/list/turfs = list() - for(var/datum/air_group/turf/turf_AG in groups_to_rebuild) //Deconstruct groups, gathering their old members - for(var/turf/simulated/T in turf_AG.members) + for(var/datum/air_group/AG in groups_to_rebuild) //Deconstruct groups, gathering their old members + for(var/turf/simulated/T in AG.members) T.parent = null turfs += T - del(turf_AG) + del(AG) for(var/turf/simulated/S in turfs) //Have old members try to form new groups if(!S.parent) @@ -307,37 +258,4 @@ datum for(var/turf/simulated/S in turfs) S.update_air_properties() -// var/obj/movable/list/movable_objects = list() - - for(var/datum/air_group/object/object_AG in groups_to_rebuild) //Deconstruct groups, gathering their old members -/* - for(var/obj/movable/floor/OM in object_AG.members) - OM.parent = null - movable_objects += OM - del(object_AG) - - for(var/obj/movable/floor/OM in movable_objects) //Have old members try to form new groups - if(!OM.parent) - assemble_group_object(OM) - for(var/obj/movable/floor/OM in movable_objects) - OM.update_air_properties() -*/ - groups_to_rebuild.len = 0 - - process_groups() - for(var/datum/air_group/AG in air_groups) - AG.process_group() - - process_singletons() - for(var/turf/simulated/T in active_singletons) - T.process_cell() - - process_super_conductivity() - for(var/turf/simulated/hot_potato in active_super_conductivity) - hot_potato.super_conduct() - - process_high_pressure_delta() - for(var/turf/pressurized in high_pressure_delta) - pressurized.high_pressure_movements() - - high_pressure_delta.len = 0 + groups_to_rebuild = list() diff --git a/code/FEA/FEA_turf_tile.dm b/code/FEA/FEA_turf_tile.dm index 3dd1204c2ac..fa4081b8afe 100644 --- a/code/FEA/FEA_turf_tile.dm +++ b/code/FEA/FEA_turf_tile.dm @@ -49,8 +49,8 @@ turf var/pressure_direction = 0 //optimization vars - var/next_check = 0 //number of ticks before this tile updates - var/check_delay = 0 //number of ticks between updates +// var/next_check = 0 //number of ticks before this tile updates +// var/check_delay = 0 //number of ticks between updates proc high_pressure_movements() @@ -95,7 +95,7 @@ turf datum/gas_mixture/air processing = 1 - datum/air_group/turf/parent + datum/air_group/parent group_border = 0 length_space_border = 0 @@ -192,8 +192,8 @@ turf parent.suspend_group_processing() air.merge(giver) else - if (giver.total_moles > MINIMUM_AIR_TO_SUSPEND) - reset_delay() +// if (giver.total_moles > MINIMUM_AIR_TO_SUSPEND) +// reset_delay() air.merge(giver) @@ -292,7 +292,7 @@ turf if(air_check_directions) processing = 1 if(!parent) - air_master.add_singleton(src) + air_master.active_singletons |= src else processing = 0 @@ -302,11 +302,11 @@ turf //and doesn't afraid of anything //check if we're skipping this tick - if (next_check > 0) - next_check-- - return 1 - next_check += check_delay + rand(0,check_delay/2) - check_delay++ +// if (next_check > 0) +// next_check-- +// return 1 +// next_check += check_delay + rand(0,check_delay/2) +// check_delay++ var/turf/simulated/list/possible_fire_spreads = list() if(processing) @@ -323,11 +323,11 @@ turf if(enemy_tile.archived_cycle < archived_cycle) //archive bordering tile information if not already done enemy_tile.archive() - if (air && enemy_tile.air) - var/delay_trigger = air.compare(enemy_tile.air) - if (!delay_trigger) //if compare() didn't return 1, air is different enough to trigger processing - reset_delay() - enemy_tile.reset_delay() +// if (air && enemy_tile.air) +// var/delay_trigger = air.compare(enemy_tile.air) +// if (!delay_trigger) //if compare() didn't return 1, air is different enough to trigger processing +// reset_delay() +// enemy_tile.reset_delay() if(enemy_tile.parent && enemy_tile.parent.group_processing) //apply tile to group sharing if(enemy_tile.parent.current_cycle < current_cycle) //if the group hasn't been archived, it could just be out of date @@ -392,7 +392,7 @@ turf update_visuals(air) if(air.temperature > FIRE_MINIMUM_TEMPERATURE_TO_EXIST) - reset_delay() //hotspots always process quickly +// reset_delay() //hotspots always process quickly hotspot_expose(air.temperature, CELL_VOLUME) for(var/atom/movable/item in src) item.temperature_expose(air, air.temperature, CELL_VOLUME) @@ -564,11 +564,11 @@ turf air_master.active_super_conductivity += src - proc/reset_delay() +// proc/reset_delay() //sets this turf to process quickly again - next_check=0 - check_delay= -5 //negative numbers mean a mandatory quick-update period +// next_check=0 +// check_delay= -5 //negative numbers mean a mandatory quick-update period //if this turf has a parent air group, suspend its processing - if (parent && parent.group_processing) - parent.suspend_group_processing() +// if (parent && parent.group_processing) +// parent.suspend_group_processing() diff --git a/code/FEA/FEA_variables.dm b/code/FEA/FEA_variables.dm new file mode 100644 index 00000000000..10d75864c67 --- /dev/null +++ b/code/FEA/FEA_variables.dm @@ -0,0 +1,631 @@ +//Please note that mose of these variables are holdovers form ZAS, but I really do not want to expend the effort to prune it down quite yet. + +pl_control/var + PLASMA_DMG = 3 + PLASMA_DMG_NAME = "Plasma Damage Multiplier" + PLASMA_DMG_DESC = "Multiplier on how much damage inhaling plasma can do." + + OXY_TO_PLASMA = 1 + OXY_TO_PLASMA_NAME = "O2/Plasma Ratio" + OXY_TO_PLASMA_DESC = "Multiplier for the ratio of oxygen to plasma required in fires." + + CLOTH_CONTAMINATION = 1 //If this is on, plasma does damage by getting into cloth. + CLOTH_CONTAMINATION_NAME = "Plasma - Cloth Contamination" + CLOTH_CONTAMINATION_RANDOM = 60 + CLOTH_CONTAMINATION_METHOD = "Toggle" + CLOTH_CONTAMINATION_DESC = "If set to nonzero, plasma will contaminate cloth items (uniforms, backpacks, etc.)\ + and cause a small amount of damage over time to anyone carrying or wearing them. Contamination can be detected\ + with a Health Analyzer, and washed off in the washer." + + ALL_ITEM_CONTAMINATION = 0 //If this is on, any item can be contaminated, so suits and tools must be discarded or + //decontaminated. + ALL_ITEM_CONTAMINATION_NAME = "Plasma - Full Contamination" + ALL_ITEM_CONTAMINATION_RANDOM = 10 + ALL_ITEM_CONTAMINATION_METHOD = "Toggle" + ALL_ITEM_CONTAMINATION_DESC = "Like Cloth Contamination, but all item types are susceptible." + + PLASMAGUARD_ONLY = 0 + PLASMAGUARD_ONLY_NAME = "Plasma - Biosuits/Spacesuits Only" + PLASMAGUARD_ONLY_RANDOM = 20 + PLASMAGUARD_ONLY_METHOD = "Toggle" + PLASMAGUARD_ONLY_DESC = "If on, any suits that are not biosuits or space suits will not protect against contamination." + + //CANISTER_CORROSION = 0 //If this is on, plasma must be stored in orange tanks and canisters, + //CANISTER_CORROSION_RANDOM = 20 //or it will corrode the tank. + //CANISTER_CORROSION_METHOD = "Toggle" + + GENETIC_CORRUPTION = 0 //Chance of genetic corruption as well as toxic damage, X in 10,000. + GENETIC_CORRUPTION_NAME = "Plasma - Genetic Corruption" + GENETIC_CORRUPTION_RANDOM = "PROB10/3d6" + GENETIC_CORRUPTION_METHOD = "Numeric" + GENETIC_CORRUPTION_DESC = "When set to a probability in 1000, any humans in plasma will have this chance to develop a random mutation." + + SKIN_BURNS = 1 //Plasma has an effect similar to mustard gas on the un-suited. + SKIN_BURNS_NAME = "Plasma - Skin Burns" + SKIN_BURNS_RANDOM = 10 + SKIN_BURNS_METHOD = "Toggle" + SKIN_BURNS_DESC = "When toggled, humans with exposed skin will suffer burns (similar to mustard gas) in plasma." + + //PLASMA_INJECTS_TOXINS = 0 //Plasma damage injects the toxins chemical to do damage over time. + //PLASMA_INJECTS_TOXINS_RANDOM = 30 + //PLASMA_INJECTS_TOXINS_METHOD = "Toggle" + + EYE_BURNS = 0 //Plasma burns the eyes of anyone not wearing eye protection. + EYE_BURNS_NAME = "Plasma - Eye Burns" + EYE_BURNS_RANDOM = 30 + EYE_BURNS_METHOD = "Toggle" + EYE_BURNS_DESC = "When toggled, humans without masks that cover the eyes will suffer temporary blurriness and sight loss,\ + and may need glasses to see again if exposed for long durations." + + //N2O_REACTION = 0 //Plasma can react with N2O, making sparks and starting a fire if levels are high. + //N2O_REACTION_RANDOM = 5 + + //PLASMA_COLOR = "onturf" //Plasma can change colors yaaaay! + //PLASMA_COLOR_RANDOM = "PICKonturf,onturf" + + //PLASMA_DMG_OFFSET = 1 + //PLASMA_DMG_OFFSET_RANDOM = "1d5" + //PLASMA_DMG_QUOTIENT = 10 + //PLASMA_DMG_QUOTIENT_RANDOM = "1d10+4" + + CONTAMINATION_LOSS = 0.1 + _NAME = "Plasma - Contamination Damage" + CONTAMINATION_LOSS_DESC = "A number representing the damage done per life cycle by contaminated items." + + PLASMA_HALLUCINATION = 1 + PLASMA_HALLUCINATION_NAME = "Plasma - Hallucination" + PLASMA_HALLUCINATION_METHOD = "Toggle" + PLASMA_HALLUCINATION_DESC = "If toggled, uses the remnants of the hallucination code to induce visions in those\ + who breathe plasma." + N2O_HALLUCINATION = 1 + N2O_HALLUCINATION_NAME = "Nitrous Oxide - Hallucination" + N2O_HALLUCINATION_METHOD = "Toggle" + N2O_HALLUCINATION_DESC = "If toggled, uses the remnants of the hallucination code to induce visions in those\ + who breathe N2O." + //CONTAMINATION_LOSS_RANDOM = "5d5" +//Plasma has a chance to be a different color. + +var/tick_multiplier = 2 +/datum/controller/air_system/var + //Used in /mob/carbon/human/life + OXYGEN_LOSS = 2 + OXYGEN_LOSS_NAME = "Damage - Oxygen Loss" + OXYGEN_LOSS_DESC = "A multiplier for damage due to lack of air, CO2 poisoning, and vacuum. Does not affect oxyloss\ + from being incapacitated or dying." + TEMP_DMG = 2 + TEMP_DMG_NAME = "Damage - Temperature" + TEMP_DMG_DESC = "A multiplier for damage due to body temperature irregularities." + BURN_DMG = 6 + BURN_DMG_NAME = "Damage - Fire" + BURN_DMG_DESC = "A multiplier for damage due to direct fire exposure." + + AF_TINY_MOVEMENT_THRESHOLD = 50 //% difference to move tiny items. + AF_TINY_MOVEMENT_THRESHOLD_NAME = "Airflow - Tiny Movement Threshold %" + AF_TINY_MOVEMENT_THRESHOLD_DESC = "Percent of 1 Atm. at which items with the tiny weight class will move." + AF_SMALL_MOVEMENT_THRESHOLD = 70 //% difference to move small items. + AF_SMALL_MOVEMENT_THRESHOLD_NAME = "Airflow - Small Movement Threshold %" + AF_SMALL_MOVEMENT_THRESHOLD_DESC = "Percent of 1 Atm. at which items with the small weight class will move." + AF_NORMAL_MOVEMENT_THRESHOLD = 90 //% difference to move normal items. + AF_NORMAL_MOVEMENT_THRESHOLD_NAME = "Airflow - Normal Movement Threshold %" + AF_NORMAL_MOVEMENT_THRESHOLD_DESC = "Percent of 1 Atm. at which items with the normal weight class will move." + AF_LARGE_MOVEMENT_THRESHOLD = 100 //% difference to move large and huge items. + AF_LARGE_MOVEMENT_THRESHOLD_NAME = "Airflow - Large Movement Threshold %" + AF_LARGE_MOVEMENT_THRESHOLD_DESC = "Percent of 1 Atm. at which items with the large or huge weight class will move." + AF_DENSE_MOVEMENT_THRESHOLD = 120 //% difference to move dense crap and mobs. + AF_DENSE_MOVEMENT_THRESHOLD_NAME = "Airflow - Dense Movement Threshold %" + AF_DENSE_MOVEMENT_THRESHOLD_DESC = "Percent of 1 Atm. at which dense objects (canisters, etc.) will be shifted by airflow." + AF_MOB_MOVEMENT_THRESHOLD = 175 + AF_MOB_MOVEMENT_THRESHOLD_NAME = "Airflow - Human Movement Threshold %" + AF_MOB_MOVEMENT_THRESHOLD_DESC = "Percent of 1 Atm. at which mobs will be shifted by airflow." + + AF_HUMAN_STUN_THRESHOLD = 130 + AF_HUMAN_STUN_THRESHOLD_NAME = "Airflow - Human Stun Threshold %" + AF_HUMAN_STUN_THRESHOLD_DESC = "Percent of 1 Atm. at which living things are stunned or knocked over." + + AF_PERCENT_OF = ONE_ATMOSPHERE + AF_PERCENT_OF_NAME = "Airflow - 100% Pressure" + AF_PERCENT_OF_DESC = "Normally set to 1 Atm. in kPa, this indicates what pressure is considered 100% by the system." + + AF_SPEED_MULTIPLIER = 4 //airspeed per movement threshold value crossed. + AF_SPEED_MULTIPLIER_NAME = "Airflow - Speed Increase per 10%" + AF_SPEED_MULTIPLIER_DESC = "Velocity increase of shifted items per 10% of airflow." + AF_DAMAGE_MULTIPLIER = 5 //Amount of damage applied per airflow_speed. + AF_DAMAGE_MULTIPLIER_NAME = "Airflow - Damage Per Velocity" + AF_DAMAGE_MULTIPLIER_DESC = "Amount of damage applied per unit of speed (1-15 units) at which mobs are thrown." + AF_STUN_MULTIPLIER = 1.5 //Seconds of stun applied per airflow_speed. + AF_STUN_MULTIPLIER_NAME = "Airflow - Stun Per Velocity" + AF_STUN_MULTIPLIER_DESC = "Amount of stun effect applied per unit of speed (1-15 units) at which mobs are thrown." + AF_SPEED_DECAY = 0.5 //Amount that flow speed will decay with time. + AF_SPEED_DECAY_NAME = "Airflow - Velocity Lost per Tick" + AF_SPEED_DECAY_DESC = "Amount of airflow speed lost per tick on a moving object." + AF_SPACE_MULTIPLIER = 2 //Increasing this will make space connections more DRAMATIC! + AF_SPACE_MULTIPLIER_NAME = "Airflow - Space Airflow Multiplier" + AF_SPACE_MULTIPLIER_DESC = "Increasing this multiplier will cause more powerful airflow to space." + AF_CANISTER_MULTIPLIER = 0.25 + AF_CANISTER_MULTIPLIER_NAME = "Airflow - Canister Airflow Multiplier" + AF_CANISTER_MULTIPLIER_DESC = "Increasing this multiplier will cause more powerful airflow from single-tile sources like canisters." + +/datum/controller/air_system + var + list/settings = list() + list/bitflags = list("1","2","4","8","16","32","64","128","256","512","1024") + pl_control/plc = new() + 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 + + 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 plc.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) + var/vw + var/how = "Text" + if(ch in plc.settings) + vw = plc.vars[ch] + if("[ch]_METHOD" in vars) + how = plc.vars["[ch]_METHOD"] + else + if(isnum(vw)) + how = "Numeric" + else + how = "Text" + else + vw = vars[ch] + if("[ch]_METHOD" in vars) + how = vars["[ch]_METHOD"] + 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 + else + vars[ch] = vw + if(how == "Toggle") + newvar = (newvar?"ON":"OFF") + world << "\blue [key_name(user)] changed the setting [ch] to [newvar]." + //user << "[which] has been changed 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 + + proc/ChangePlasma() + for(var/V in plc.settings) + plc.Randomize(V) + ////world << "Plasma randomized." + + proc/SetDefault(def) + switch(def) + if("Original") + plc.CLOTH_CONTAMINATION = 0 //If this is on, plasma does damage by getting into cloth. + + plc.ALL_ITEM_CONTAMINATION = 0 //If this is on, any item can be contaminated, so suits and tools must be discarded or + + plc.PLASMAGUARD_ONLY = 0 + + //plc.CANISTER_CORROSION = 0 //If this is on, plasma must be stored in orange tanks and canisters, + + 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.PLASMA_INJECTS_TOXINS = 0 //Plasma damage injects the toxins chemical to do damage over time. + + plc.EYE_BURNS = 0 //Plasma burns the eyes of anyone not wearing eye protection. + + //plc.N2O_REACTION = 0 //Plasma can react with N2O, making sparks and starting a fire if levels are high. + + //plc.PLASMA_COLOR = "onturf" //Plasma can change colors yaaaay! + + //plc.PLASMA_DMG_OFFSET = 1 + //plc.PLASMA_DMG_QUOTIENT = 10 + + plc.CONTAMINATION_LOSS = 0 + if("Hazard-Low") + plc.CLOTH_CONTAMINATION = 1 //If this is on, plasma does damage by getting into cloth. + + plc.ALL_ITEM_CONTAMINATION = 0 //If this is on, any item can be contaminated, so suits and tools must be discarded or + + plc.PLASMAGUARD_ONLY = 0 + + // plc.CANISTER_CORROSION = 0 //If this is on, plasma must be stored in orange tanks and canisters, + + 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.PLASMA_INJECTS_TOXINS = 0 //Plasma damage injects the toxins chemical to do damage over time. + + plc.EYE_BURNS = 0 //Plasma burns the eyes of anyone not wearing eye protection. + + // plc.N2O_REACTION = 0 //Plasma can react with N2O, making sparks and starting a fire if levels are high. + + // plc.PLASMA_COLOR = "onturf" //RBPYB + + //if(prob(20)) + // plc.PLASMA_COLOR = pick("red","yellow","blue","purple") + + //plc.PLASMA_DMG_OFFSET = 1.5 + //plc.PLASMA_DMG_QUOTIENT = 8 + + plc.CONTAMINATION_LOSS = 0.01 + + var/s = pick(plc.settings) + plc.Randomize(s) + + if("Hazard-High") + plc.CLOTH_CONTAMINATION = 1 //If this is on, plasma does damage by getting into cloth. + + plc.ALL_ITEM_CONTAMINATION = 0 //If this is on, any item can be contaminated, so suits and tools must be discarded or + + plc.PLASMAGUARD_ONLY = 0 + + // plc.CANISTER_CORROSION = 1 //If this is on, plasma must be stored in orange tanks and canisters, + + 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.PLASMA_INJECTS_TOXINS = 0 //Plasma damage injects the toxins chemical to do damage over time. + + plc.EYE_BURNS = 0 //Plasma burns the eyes of anyone not wearing eye protection. + + // plc.N2O_REACTION = 0 //Plasma can react with N2O, making sparks and starting a fire if levels are high. + + // plc.PLASMA_COLOR = "onturf"//pick("red","yellow","blue","purple") //RBPYB + + //plc.PLASMA_DMG_OFFSET = 3 + //plc.PLASMA_DMG_QUOTIENT = 5 + + plc.CONTAMINATION_LOSS = 0.05 + + for(var/i = rand(3,5),i>0,i--) + var/s = pick(plc.settings) + plc.Randomize(s) + + if("Everything") + plc.CLOTH_CONTAMINATION = 1 //If this is on, plasma does damage by getting into cloth. + + plc.ALL_ITEM_CONTAMINATION = 1 //If this is on, any item can be contaminated, so suits and tools must be discarded or ELSE + + plc.PLASMAGUARD_ONLY = 1 + + // plc.CANISTER_CORROSION = 1 //If this is on, plasma must be stored in orange tanks and canisters, + + 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.PLASMA_INJECTS_TOXINS = 1 //Plasma damage injects the toxins chemical to do damage over time. + + plc.EYE_BURNS = 1 //Plasma burns the eyes of anyone not wearing eye protection. + + // plc.N2O_REACTION = 1 //Plasma can react with N2O, making sparks and starting a fire if levels are high. + + // plc.PLASMA_COLOR = "onturf" //RBPYB + + //plc.PLASMA_DMG_OFFSET = 3 + //plc.PLASMA_DMG_QUOTIENT = 5 + + plc.CONTAMINATION_LOSS = 0.02 + /////world << "Plasma color updated." + +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) + //world << "Randomizing [V]" + var/newvalue + if("[V]_RANDOM" in vars) + if(isnum(vars["[V]_RANDOM"])) + newvalue = prob(vars["[V]_RANDOM"]) + if(newvalue) + //world << "Probability [vars["[V]_RANDOM"]]%: Success." + else + //world << "Probability [vars["[V]_RANDOM"]]%: Failure." + else if(istext(vars["[V]_RANDOM"])) + var/txt = vars["[V]_RANDOM"] + if(findtextEx(txt,"PROB")) + //world << "Probability/Roll Combo \..." + txt = dd_text2list(txt,"/") + txt[1] = dd_replacetext(txt[1],"PROB","") + var/p = text2num(txt[1]) + var/r = txt[2] + //world << "Prob:[p]% Roll:[r]" + if(prob(p)) + newvalue = roll(r) + //world << "Success. New value: [newvalue]" + else + newvalue = vars[V] + //world << "Probability check failed." + else if(findtextEx(txt,"PICK")) + txt = dd_replacetext(txt,"PICK","") + //world << "Pick: [txt]" + txt = dd_text2list(txt,",") + newvalue = pick(txt) + //world << "Picked: [newvalue]" + else + newvalue = roll(txt) + //world << "Roll: [txt] - [newvalue]" + else + newvalue = vars[V] + vars[V] = newvalue + ////world << "Plasma color updated." + +mob/proc/Change_Airflow_Constants() + set category = "Debug" + + var/choice = input("Which constant will you modify?","Change Airflow Constants")\ + as null|anything in list("Movement Threshold","Speed Multiplier","Damage Multiplier","Stun Multiplier","Speed Decay") + + var/n + + switch(choice) + if("Movement Threshold") + n = input("What will you change it to","Change Airflow Constants",air_master.AF_DENSE_MOVEMENT_THRESHOLD) as num + n = max(1,n) + air_master.AF_DENSE_MOVEMENT_THRESHOLD = n + world.log << "air_master.AF_DENSE_MOVEMENT_THRESHOLD set to [n]." + if("Speed Multiplier") + n = input("What will you change it to","Change Airflow Constants",air_master.AF_SPEED_MULTIPLIER) as num + n = max(1,n) + air_master.AF_SPEED_MULTIPLIER = n + world.log << "air_master.AF_SPEED_MULTIPLIER set to [n]." + if("Damage Multiplier") + n = input("What will you change it to","Change Airflow Constants",air_master.AF_DAMAGE_MULTIPLIER) as num + air_master.AF_DAMAGE_MULTIPLIER = n + world.log << "AF_DAMAGE_MULTIPLIER set to [n]." + if("Stun Multiplier") + n = input("What will you change it to","Change Airflow Constants",air_master.AF_STUN_MULTIPLIER) as num + air_master.AF_STUN_MULTIPLIER = n + world.log << "AF_STUN_MULTIPLIER set to [n]." + if("Speed Decay") + n = input("What will you change it to","Change Airflow Constants",air_master.AF_SPEED_DECAY) as num + air_master.AF_SPEED_DECAY = n + world.log << "AF_SPEED_DECAY set to [n]." + if("Space Flow Multiplier") + n = input("What will you change it to","Change Airflow Constants",air_master.AF_SPEED_DECAY) as num + air_master.AF_SPEED_DECAY = n + world.log << "AF_SPEED_DECAY set to [n]." + +obj/var/contaminated = 0 + +obj/item/proc + can_contaminate() + if(flags & PLASMAGUARD) return 0 + if((flags & SUITSPACE) && !air_master.plc.PLASMAGUARD_ONLY) return 1 + if(air_master.plc.ALL_ITEM_CONTAMINATION) return 1 + else if(istype(src,/obj/item/clothing)) return 1 + else if(istype(src,/obj/item/weapon/storage/backpack)) return 1 + +/mob/living/carbon/human/proc/contaminate() + if(!pl_suit_protected()) + suit_contamination() + else if(air_master.plc.PLASMAGUARD_ONLY) + if(!wear_suit.flags & PLASMAGUARD) wear_suit.contaminated = 1 + + + + if(!pl_head_protected()) + if(wear_mask) wear_mask.contaminated = 1 + if(prob(1)) suit_contamination() //Plasma can sometimes get through such an open suit. + else if(air_master.plc.PLASMAGUARD_ONLY) + if(!head.flags & PLASMAGUARD) head.contaminated = 1 + + if(istype(back,/obj/item/weapon/storage/backpack) || air_master.plc.ALL_ITEM_CONTAMINATION) + back.contaminated = 1 + + if(l_hand) + if(l_hand.can_contaminate()) l_hand.contaminated = 1 + if(r_hand) + if(r_hand.can_contaminate()) r_hand.contaminated = 1 + if(belt) + if(belt.can_contaminate()) belt.contaminated = 1 + if(wear_id && !pl_suit_protected()) + if(wear_id.can_contaminate()) wear_id.contaminated = 1 + if(l_ear && !pl_head_protected()) + if(l_ear.can_contaminate()) l_ear.contaminated = 1 + if(r_ear && !pl_head_protected()) + if(r_ear.can_contaminate()) r_ear.contaminated = 1 + +/mob/living/carbon/human/proc/pl_effects() + if(stat >= 2) + return + if(air_master.plc.SKIN_BURNS) + if(!pl_head_protected() || !pl_suit_protected()) + burn_skin(0.75) + if (coughedtime != 1) + coughedtime = 1 + emote("gasp") + spawn (20) + coughedtime = 0 + updatehealth() + if(air_master.plc.EYE_BURNS && !pl_head_protected()) + if(!wear_mask) + if(prob(20)) usr << "\red Your eyes burn!" + eye_stat += 2.5 + eye_blurry += 1.5 + if (eye_stat >= 20 && !(disabilities & 1)) + src << "\red Your eyes start to burn badly!" + disabilities |= 1 + if (prob(max(0,eye_stat - 20) + 1)) + src << "\red You are blinded!" + eye_blind += 20 + eye_stat = max(eye_stat-25,0) + else + if(!(wear_mask.flags & MASKCOVERSEYES)) + if(prob(20)) usr << "\red Your eyes burn!" + eye_stat += 2.5 + eye_blurry = min(eye_blurry+1.5,50) + if (eye_stat >= 20 && !(disabilities & 1)) + src << "\red Your eyes start to burn badly!" + disabilities |= 1 + if (prob(max(0,eye_stat - 20) + 1) &&!eye_blind) + src << "\red You are blinded!" + eye_blind += 20 + eye_stat = 0 + if(air_master.plc.GENETIC_CORRUPTION) + if(rand(1,1000) < air_master.plc.GENETIC_CORRUPTION) + randmutb(src) + src << "\red High levels of toxins cause you to spontaneously mutate." + domutcheck(src,null) + +/mob/living/carbon/human/proc/FireBurn(mx as num) + //NO! NOT INTO THE PIT! IT BURRRRRNS! + mx *= air_master.BURN_DMG + + var + head_exposure = 1 + chest_exposure = 1 + groin_exposure = 1 + legs_exposure = 1 + feet_exposure = 1 + arms_exposure = 1 + hands_exposure = 1 + for(var/obj/item/clothing/C in src) + if(l_hand == C || r_hand == C) continue + if(C.body_parts_covered & HEAD) + head_exposure *= C.heat_transfer_coefficient + if(C.body_parts_covered & UPPER_TORSO) + chest_exposure *= C.heat_transfer_coefficient + if(C.body_parts_covered & LOWER_TORSO) + groin_exposure *= C.heat_transfer_coefficient + if(C.body_parts_covered & LEGS) + legs_exposure *= C.heat_transfer_coefficient + if(C.body_parts_covered & FEET) + feet_exposure *= C.heat_transfer_coefficient + if(C.body_parts_covered & ARMS) + arms_exposure *= C.heat_transfer_coefficient + if(C.body_parts_covered & HANDS) + arms_exposure *= C.heat_transfer_coefficient + + mx *= 10 + + apply_damage("head", 0, 2.5*mx*head_exposure) + apply_damage("chest", 0, 2.5*mx*chest_exposure) + apply_damage("groin", 0, 2.0*mx*groin_exposure) + apply_damage("l_leg", 0, 0.6*mx*legs_exposure) + apply_damage("r_leg", 0, 0.6*mx*legs_exposure) + apply_damage("l_arm", 0, 0.4*mx*arms_exposure) + apply_damage("r_arm", 0, 0.4*mx*arms_exposure) + apply_damage("l_foot", 0, 0.25*mx*feet_exposure) + apply_damage("r_foot", 0, 0.25*mx*feet_exposure) + apply_damage("l_hand", 0, 0.25*mx*hands_exposure) + apply_damage("r_hand", 0, 0.25*mx*hands_exposure) + +/mob/living/carbon/human/proc/suit_interior() + . = list() + if(!pl_suit_protected()) + for(var/obj/item/I in src) + . += I + return . + . += wear_mask + . += w_uniform + . += shoes + . += gloves + if(!pl_head_protected()) + . += head + +/mob/living/carbon/human/proc/pl_head_protected() + if(head) + if(head.flags & PLASMAGUARD || head.flags & HEADSPACE) return 1 + return 0 + +/mob/living/carbon/human/proc/pl_suit_protected() + if(wear_suit) + if(wear_suit.flags & PLASMAGUARD || wear_suit.flags & SUITSPACE) return 1 + return 0 + +/mob/living/carbon/human/proc/suit_contamination() + if(air_master.plc.ALL_ITEM_CONTAMINATION) + for(var/obj/item/I in src) + I.contaminated = 1 + else + if(wear_suit) wear_suit.contaminated = 1 + if(w_uniform) w_uniform.contaminated = 1 + if(shoes) shoes.contaminated = 1 + if(gloves) gloves.contaminated = 1 + if(wear_mask) wear_mask.contaminated = 1 + + +turf/Entered(obj/item/I) + . = ..() + if(istype(I)) + var/datum/gas_mixture/env = return_air(1) + if(env.toxins > 0.35) + if(I.can_contaminate()) + I.contaminated = 1 \ No newline at end of file diff --git a/code/WorkInProgress/Cael_Aislinn/Supermatter/SuperMatter.dm b/code/WorkInProgress/Cael_Aislinn/Supermatter/SuperMatter.dm index 0bcb010bf4c..5661f8d212d 100644 --- a/code/WorkInProgress/Cael_Aislinn/Supermatter/SuperMatter.dm +++ b/code/WorkInProgress/Cael_Aislinn/Supermatter/SuperMatter.dm @@ -60,6 +60,11 @@ //a lot of these variables are pretty hacked, so dont rely on the comments /obj/machinery/power/supermatter/process() + var/datum/gas_mixture/env = loc.return_air() + + //Remove gas from surrounding area + var/transfer_moles = gasefficency * env.total_moles + var/datum/gas_mixture/removed = env.remove(transfer_moles) //core can no longer spontaneously explode /* @@ -110,15 +115,15 @@ //nothing can happen in a vacuum var/datum/gas_mixture/removed = env var/retardation_factor = 0.5 - if(env.total_moles()) + if(env.total_moles) //Remove gas from surrounding area - var/transfer_moles = gasefficency * env.total_moles() + var/transfer_moles = gasefficency * env.total_moles removed = env.remove(transfer_moles) //100% oxygen atmosphere = 100% plasma production //100% nitrogen atmosphere = 0% plasma production //anything else is halfway in between; an atmosphere with no nitrogen or oxygen will still be at 50% (but steadily rise as more oxygen is made) - var/total_moles = removed.total_moles() + var/total_moles = removed.total_moles if(total_moles) retardation_factor += removed.oxygen / (total_moles * 2) - removed.nitrogen / (total_moles * 2) else @@ -143,6 +148,7 @@ // produced = device_energy * OXYGEN_RELEASE_MODIFIER * retardation_factor removed.oxygen += produced + removed.update_values() // mega_energy = 0 diff --git a/code/WorkInProgress/Ported/ZeroPoint/SuperMatter.dm b/code/WorkInProgress/Ported/ZeroPoint/SuperMatter.dm deleted file mode 100644 index 9b77e9626b0..00000000000 --- a/code/WorkInProgress/Ported/ZeroPoint/SuperMatter.dm +++ /dev/null @@ -1,120 +0,0 @@ -#define NITROGEN_RETARDATION_FACTOR 4 //Higher == N2 slows reaction more -#define THERMAL_RELEASE_MODIFIER 50 //Higher == less heat released during reaction -#define PLASMA_RELEASE_MODIFIER 750 //Higher == less plasma released by reaction -#define OXYGEN_RELEASE_MODIFIER 1500 //Higher == less oxygen released at high temperature/power -#define REACTION_POWER_MODIFIER 1.1 //Higher == more overall power - -/obj/machinery/engine/supermatter - name = "Supermatter" - desc = "A strangely translucent and iridescent crystal. \red You get headaches just from looking at it." - icon = 'engine.dmi' - icon_state = "darkmatter" - density = 1 - anchored = 1 - - var/gasefficency = 0.25 - - var/det = 0 - var/previousdet = 0 - var/const/explosiondet = 3500 - - var/const/warningtime = 50 // Make the CORE OVERLOAD message repeat only every aprox. ?? seconds - var/lastwarning = 0 // Time in 1/10th of seconds since the last sent warning - -/obj/machinery/engine/klaxon - name = "Emergency Klaxon" - icon = 'engine.dmi' - icon_state = "darkmatter" - density = 1 - anchored = 1 - var/obj/machinery/engine/supermatter/sup - -/obj/machinery/engine/klaxon/process() - if(!sup) - for(var/obj/machinery/engine/supermatter/T in world) - sup = T - break - if(sup.det >= 1) - return - -/obj/machinery/engine/supermatter/process() - - var/turf/simulated/L = loc - - //Ok, get the air from the turf - var/datum/gas_mixture/env = L.return_air() - - //Remove gas from surrounding area - var/transfer_moles = gasefficency * env.total_moles - var/datum/gas_mixture/removed = env.remove(transfer_moles) - - previousdet = det - det += (removed.temperature - 1000) / 150 - det = max(det, 0) - - if(det > 0 && removed.temperature > 1000) // while the core is still damaged and it's still worth noting its status - if((world.realtime - lastwarning) / 10 >= warningtime) - lastwarning = world.realtime - if(explosiondet - det <= 300) - radioalert("CORE EXPLOSION IMMINENT","Core control computer") - else if(det >= previousdet) // The damage is still going up - radioalert("CORE OVERLOAD","Core control computer") - else // Phew, we're safe - radioalert("Core returning to safe operating levels.","Core control computer") - - if(det > explosiondet) - roundinfo.core = 1 - //proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, force = 0) - explosion(src.loc,8,15,20,30,1) - det = 0 - - if (!removed) - return 1 - - var/power = max(round((removed.temperature - T0C) / 20), 0) //Total laser power plus an overload factor - - //Get the collective laser power - for(var/dir in cardinal) - var/turf/T = get_step(L, dir) - for(var/obj/effect/beam/e_beam/item in T) - power += item.power - - //Ok, 100% oxygen atmosphere = best reaction - //Maxes out at 100% oxygen pressure - var/oxygen = max(min((removed.oxygen - (removed.nitrogen * NITROGEN_RETARDATION_FACTOR)) / MOLES_CELLSTANDARD, 1), 0) - - var/device_energy = oxygen * power - - device_energy *= removed.temperature / T0C - - device_energy = round(device_energy * REACTION_POWER_MODIFIER) - - //To figure out how much temperature to add each tick, consider that at one atmosphere's worth - //of pure oxygen, with all four lasers firing at standard energy and no N2 present, at room temperature - //that the device energy is around 2140. At that stage, we don't want too much heat to be put out - //Since the core is effectively "cold" - - //Also keep in mind we are only adding this temperature to (efficiency)% of the one tile the rock - //is on. An increase of 4*C @ 25% efficiency here results in an increase of 1*C / (#tilesincore) overall. - removed.temperature += max((device_energy / THERMAL_RELEASE_MODIFIER), 0) - - removed.temperature = min(removed.temperature, 1500) - - //Calculate how much gas to release - removed.toxins += max(round(device_energy / PLASMA_RELEASE_MODIFIER), 0) - - removed.oxygen += max(round((device_energy + removed.temperature - T0C) / OXYGEN_RELEASE_MODIFIER), 0) - - env.merge(removed) - -//Not functional currently. -- SkyMarshal -/* - for(var/mob/living/carbon/l in view(src, 6)) // you have to be seeing the core to get hallucinations - if(prob(10) && !(l.glasses && istype(l.glasses, /obj/item/clothing/glasses/meson))) - l.hallucination = 50 -*/ - for(var/mob/living/l in view(src,3)) - l.bruteloss += 50 - l.updatehealth() - - return 1 \ No newline at end of file diff --git a/code/game/machinery/atmoalter/canister.dm b/code/game/machinery/atmoalter/canister.dm index 83ca41f581d..ca37c394dda 100644 --- a/code/game/machinery/atmoalter/canister.dm +++ b/code/game/machinery/atmoalter/canister.dm @@ -289,6 +289,7 @@ Release Pressure: - - - - - - The Master Controller has fired. Automatic restart aborted." + M << " The Master Controller has fired. Automatic restart aborted." \ No newline at end of file diff --git a/code/game/objects/tank.dm b/code/game/objects/tank.dm index ed1cdbd865b..73b890be9e7 100644 --- a/code/game/objects/tank.dm +++ b/code/game/objects/tank.dm @@ -244,7 +244,6 @@ src.air_contents = new /datum/gas_mixture() src.air_contents.volume = volume //liters src.air_contents.temperature = T20C - air_contents.update_values() processing_objects.Add(src) diff --git a/code/game/objects/tanks/emergency.dm b/code/game/objects/tanks/emergency.dm index 0d767fd2700..71ca3243f12 100644 --- a/code/game/objects/tanks/emergency.dm +++ b/code/game/objects/tanks/emergency.dm @@ -11,7 +11,7 @@ New() ..() - src.air_contents.oxygen = (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) + air_contents.adjustGases((3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)) return @@ -41,10 +41,7 @@ New() ..() - src.air_contents.oxygen = (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * O2STANDARD - var/datum/gas/sleeping_agent/trace_gas = new() trace_gas.moles = (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * N2STANDARD - - src.air_contents.trace_gases += trace_gas + air_contents.adjustGases((3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * O2STANDARD, traces = list(trace_gas)) return \ No newline at end of file diff --git a/code/game/objects/tanks/jetpack.dm b/code/game/objects/tanks/jetpack.dm index 7e829f4a9a0..a8b853b6b7c 100644 --- a/code/game/objects/tanks/jetpack.dm +++ b/code/game/objects/tanks/jetpack.dm @@ -75,7 +75,7 @@ New() ..() - src.air_contents.oxygen = (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) + air_contents.adjustGases((6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)) return /obj/item/weapon/tank/jetpack/oxygen @@ -86,7 +86,7 @@ New() ..() - src.air_contents.oxygen = (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) + air_contents.adjustGases((6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)) return /obj/item/weapon/tank/jetpack/carbondioxide @@ -99,7 +99,7 @@ ..() src.ion_trail = new /datum/effect/effect/system/ion_trail_follow() src.ion_trail.set_up(src) - src.air_contents.carbon_dioxide = (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) + air_contents.adjustGases(0,(6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)) return examine() diff --git a/code/game/objects/tanks/oxygen.dm b/code/game/objects/tanks/oxygen.dm index 2ce809aeaa1..3c06dd0c644 100644 --- a/code/game/objects/tanks/oxygen.dm +++ b/code/game/objects/tanks/oxygen.dm @@ -8,7 +8,7 @@ New() ..() - src.air_contents.oxygen = (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) + air_contents.adjustGases((6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)) return diff --git a/code/setup.dm b/code/setup.dm index 77356bd1a5b..05e8e837728 100644 --- a/code/setup.dm +++ b/code/setup.dm @@ -138,6 +138,8 @@ var/MAX_EXPLOSION_RANGE = 14 #define BLOCKHAIR 32768 // temporarily removes the user's hair icon +#define PLASMAGUARD 65536 //Does not get contaminated by plasma. + //flags for pass_flags #define PASSTABLE 1 #define PASSGLASS 2 @@ -288,4 +290,4 @@ var/static/list/scarySounds = list('thudswoosh.ogg','Taser.ogg','armbomb.ogg','h // Maximum and minimum character ages. var/const/minimum_age = 20 -var/const/maximum_age = 65 +var/const/maximum_age = 65 \ No newline at end of file From 50f7332740d1d98f77e00ad8a6de9f2ea70f13a8 Mon Sep 17 00:00:00 2001 From: SkyMarshal Date: Tue, 1 May 2012 14:45:01 -0700 Subject: [PATCH 3/4] Lets not keep debug in, whoops. --- baystation12.dme | 1 - code/FEA/FEA_gas_mixture.dm | 35 +++++++++++------------------------ 2 files changed, 11 insertions(+), 25 deletions(-) diff --git a/baystation12.dme b/baystation12.dme index 47ceda83761..7f4ed43cdd8 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -356,7 +356,6 @@ #include "code\defines\sd_procs\constants.dm" #include "code\defines\sd_procs\direction.dm" #include "code\defines\sd_procs\math.dm" -#include "code\FEA\DEBUG_REMOVE_BEFORE_RELEASE.dm" #include "code\FEA\FEA_airgroup.dm" #include "code\FEA\FEA_fire.dm" #include "code\FEA\FEA_gas_mixture.dm" diff --git a/code/FEA/FEA_gas_mixture.dm b/code/FEA/FEA_gas_mixture.dm index dca70cfb578..0c7538c770d 100644 --- a/code/FEA/FEA_gas_mixture.dm +++ b/code/FEA/FEA_gas_mixture.dm @@ -467,16 +467,10 @@ datum // then -1 if sharer-check failed (sharing airgroup breaks?) // then 1 if both checks pass (share succesful?) - var/pressure = 1 - if(!return_pressure() || !sharer.return_pressure()) - pressure = 3 - else if(pressure < 0) - pressure = (sharer.return_pressure() / return_pressure()) - pressure = max(min(pressure,3),1) //Lets cap this. - var/delta_oxygen = max(QUANTIZE(oxygen_archived - sharer.oxygen_archived) * pressure/TRANSFER_FRACTION,oxygen) - var/delta_carbon_dioxide = max(QUANTIZE(carbon_dioxide_archived - sharer.carbon_dioxide_archived) * pressure/TRANSFER_FRACTION,carbon_dioxide) - var/delta_nitrogen = max(QUANTIZE(nitrogen_archived - sharer.nitrogen_archived) * pressure/TRANSFER_FRACTION,nitrogen) - var/delta_toxins = max(QUANTIZE(toxins_archived - sharer.toxins_archived) * pressure/TRANSFER_FRACTION,toxins) + 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) @@ -558,17 +552,10 @@ datum //Inputs: Air datum to share with //Outputs: Amount of gas exchanged (Negative if lost air, positive if gained.) - if(!sharer) return 0 - var/pressure = 1 - if(!return_pressure() || !sharer.return_pressure()) - pressure = 3 - else if(pressure < 0) - pressure = (sharer.return_pressure() / return_pressure()) - pressure = max(min(pressure,3),1) //Lets cap this. - var/delta_oxygen = max(QUANTIZE(oxygen_archived - sharer.oxygen_archived) * pressure/TRANSFER_FRACTION,oxygen) - var/delta_carbon_dioxide = max(QUANTIZE(carbon_dioxide_archived - sharer.carbon_dioxide_archived) * pressure/TRANSFER_FRACTION,carbon_dioxide) - var/delta_nitrogen = max(QUANTIZE(nitrogen_archived - sharer.nitrogen_archived) * pressure/TRANSFER_FRACTION,nitrogen) - var/delta_toxins = max(QUANTIZE(toxins_archived - sharer.toxins_archived) * pressure/TRANSFER_FRACTION,toxins) + 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) @@ -636,12 +623,12 @@ datum var/delta = 0 if(corresponding) - delta = max(QUANTIZE(trace_gas.moles_archived - corresponding.moles_archived)*pressure/TRANSFER_FRACTION,trace_gas.moles) + delta = QUANTIZE(trace_gas.moles_archived - corresponding.moles_archived)/TRANSFER_FRACTION else corresponding = new trace_gas.type() sharer.trace_gases += corresponding - delta = max(trace_gas.moles_archived*pressure/TRANSFER_FRACTION,trace_gas.moles) + delta = trace_gas.moles_archived/TRANSFER_FRACTION trace_gas.moles -= delta/group_multiplier corresponding.moles += delta/sharer.group_multiplier @@ -670,7 +657,7 @@ datum corresponding = new trace_gas.type() trace_gases += corresponding - delta = max(trace_gas.moles_archived*pressure/TRANSFER_FRACTION,trace_gas.moles) + delta = trace_gas.moles_archived/TRANSFER_FRACTION trace_gas.moles -= delta/sharer.group_multiplier corresponding.moles += delta/group_multiplier From 893529c69ee32d722e51b4f901e403bfe956c9d1 Mon Sep 17 00:00:00 2001 From: SkyMarshal Date: Fri, 11 May 2012 18:19:00 -0700 Subject: [PATCH 4/4] Fixes some FEA stuff, for a general improvement to how well the system runs. --- baystation12.dme | 3 - code/FEA/FEA_ZAS.dm | 57 -- code/FEA/FEA_ZAS_Airflow.dm | 451 ------------- code/FEA/FEA_system.dm | 1 + code/FEA/FEA_variables.dm | 631 ------------------ .../Cael_Aislinn/Supermatter/SuperMatter.dm | 6 - code/game/master_controller.dm | 2 +- code/game/vehicles/airtight/airtight.dm | 12 +- code/game/vehicles/vehicle.dm | 10 +- code/modules/admin/verbs/diagnostics.dm | 1 - 10 files changed, 13 insertions(+), 1161 deletions(-) delete mode 100644 code/FEA/FEA_ZAS.dm delete mode 100644 code/FEA/FEA_ZAS_Airflow.dm delete mode 100644 code/FEA/FEA_variables.dm diff --git a/baystation12.dme b/baystation12.dme index 7f4ed43cdd8..d007fb1cced 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -362,9 +362,6 @@ #include "code\FEA\FEA_group_helpers.dm" #include "code\FEA\FEA_system.dm" #include "code\FEA\FEA_turf_tile.dm" -#include "code\FEA\FEA_variables.dm" -#include "code\FEA\FEA_ZAS.dm" -#include "code\FEA\FEA_ZAS_Airflow.dm" #include "code\game\algorithm.dm" #include "code\game\atom_procs.dm" #include "code\game\cellautomata.dm" diff --git a/code/FEA/FEA_ZAS.dm b/code/FEA/FEA_ZAS.dm deleted file mode 100644 index 766cbe5fe4e..00000000000 --- a/code/FEA/FEA_ZAS.dm +++ /dev/null @@ -1,57 +0,0 @@ -/* AN EXPLANATION: -This file was added because I felt that the computations for movement -of air over large scales was not adequately done by FEA, and the attempt -to solve this problem, in the form of ZAS (Zone Atmos System), -simplified it too far, in my opinion, creating the effect of a single -opened air canister filling an entire room with a partial mix of that -gas with the pre-existing mix. This was slightly silly, due to large -rooms "flash filling" when you opened a canister, and the fact that the -procedures to recalculate the boundaries of the zones was far from -foolproof, and, indeed, often let air flash though solid bulkheads to -space. - -To solve this, I've both commented the hell out of the existing FEA code, -removed and/or replaced procs with more efficient procs, and added this -file, which contains some procedures for special cases, such as: - 1.) Moving large volumes of air into vacuum/lower pressure environs - (triggers when pressure behind a tile moving air to a lower - pressure exceeds an amount.) - e.g. A room of full air gets opened to a depressurised room - 2.) Dealing with pressure equalization. - (triggers when a large amount of gas is added to a room, it - follows behind the "stormfront" of gas change (Managed by FEA) - and triggers a rapid equalization of gas by utilizing a - psuedo-zone.) - e.g. Opening a tank of oxygen in a low pressure room, and after - spreading by FEA, it equalizes the pressure in the room, instead - instead of slowly flowing out like molasses. - -These procedures trigger when a check is made against the pressure changes -and situations occuring to the airgroup (if it is venting at high pressure, -airgroups will rejoin even if broken to ZAS process) will call these -specialized procs to help properly deal with these situation. ---SkyMarshal, May 2012*/ -/* WIP - - if(space_tiles) - for(var/T in space_tiles) - if(!istype(T,/turf/space)) space_tiles -= T - total_space += length(space_tiles) - if(length(space_tiles)) - space = space_tiles[1] - - if(total_space && space) - var/old_pressure = air.return_pressure() - air.temperature_mimic(space,OPEN_HEAT_TRANSFER_COEFFICIENT,total_space) - air.remove(MOLES_CELLSTANDARD * (air.group_multiplier/40) * total_space) - var/p_diff = old_pressure - air.return_pressure() - if(p_diff > vsc.AF_TINY_MOVEMENT_THRESHOLD) AirflowSpace(src,p_diff) - - air.graphic_archived = air.graphic - - air.temperature = max(TCMB,air.temperature) - - var/p_diff = (air.return_pressure()-Z.air.return_pressure())*connected_zones[Z]*(vsc.zone_share_percent/100) - if(p_diff > vsc.AF_TINY_MOVEMENT_THRESHOLD) Airflow(src,Z,p_diff) - air.share_ratio(Z.air,connected_zones[Z]*(vsc.zone_share_percent/100)) - */ \ No newline at end of file diff --git a/code/FEA/FEA_ZAS_Airflow.dm b/code/FEA/FEA_ZAS_Airflow.dm deleted file mode 100644 index 5fc42651c87..00000000000 --- a/code/FEA/FEA_ZAS_Airflow.dm +++ /dev/null @@ -1,451 +0,0 @@ -/* - -CONTAINS: -All AirflowX() procs, all Variable Setting Controls for airflow, save/load variable tweaks for airflow. - -VARIABLES: - -atom/movable/airflow_dest - The destination turf of a flying object. - -atom/movable/airflow_speed - The speed (1-15) at which a flying object is traveling to airflow_dest. Decays over time. - - -OVERLOADABLE PROCS: - -mob/airflow_stun() - Contains checks for and results of being stunned by airflow. - Called when airflow quantities exceed AF_HUMAN_STUN_THRESHOLD. - RETURNS: Null - -atom/movable/check_airflow_movable(n) - Contains checks for moving any object due to airflow. - n is the percent of 1 Atmosphere that is flowing. - RETURNS: 1 if the object moves under the air conditions, 0 if it stays put. - -atom/movable/airflow_hit(atom/A) - Contains results of hitting a solid object (A) due to airflow. - A is the dense object hit. - Use airflow_speed to determine how fast the projectile was going. - - -AUTOMATIC PROCS: - -Airflow(datum/air_group/A, datum/air_group/B, n, vae/list/turf/simulated/target) - Causes objects to fly along a pressure gradient. - Called by airflow calculations finding a high pressure gradient. A and B are two adjacent airgroups. - n is the pressure difference between them. - targets is a list of turfs between them. - -AirflowSpace(zone/A) - Causes objects to fly into space. - Called by airflow to space. A is a airgroup connected to space. - -atom/movable/GotoAirflowDest(n) -atom/movable/RepelAirflowDest(n) - Called by main airflow procs to cause the object to fly to or away from destination at speed n. - Probably shouldn't call this directly unless you know what you're - doing and have set airflow_dest. airflow_hit() will be called if the object collides with an obstacle. - -*/ - -mob/proc/airflow_stun() - //Purpose: AIRFLOW - //Called by: AIRFLOW - //Inputs: Hate - //Outputs: Sadness - - if(weakened <= 0) - src << pickweight("\red The sudden rush of air knocks you over!" = 5, "\red You get dragged off your feet by a rush of air!" = 5, "\red FUCKING AIRFLOW!" = 1) - weakened = max(weakened,5) - -mob/living/silicon/airflow_stun() - return - -mob/living/carbon/metroid/airflow_stun() - return - -mob/living/carbon/human/airflow_stun() - if(buckled) return 0 - if(wear_suit) - if(wear_suit.flags & SUITSPACE) return 0 - if(shoes) - if(shoes.flags & NOSLIP) return 0 - if(weakened <= 0) - src << pickweight("\red The sudden rush of air knocks you over!" = 5, "\red You get dragged off your feet by a rush of air!" = 5, "\red FUCKING AIRFLOW!" = 1) - weakened = max(weakened,2) - -atom/movable/proc/check_airflow_movable(n) - //Purpose: Determining if src is movable by airflow. - //Called by: AIRFLOW - //Inputs: Movement force - //Outputs: Boolean of capability to be moved. - - if(anchored && !ismob(src)) return 0 - - if(!istype(src,/obj/item) && n < air_master.AF_DENSE_MOVEMENT_THRESHOLD) return 0 - if(ismob(src) && n < air_master.AF_MOB_MOVEMENT_THRESHOLD) return 0 - - return 1 - -mob/dead/observer/check_airflow_movable() - return 0 - -mob/living/silicon/check_airflow_movable() - return 0 - - -obj/item/check_airflow_movable(n) - . = ..() - switch(w_class) - if(2) - if(n < air_master.AF_SMALL_MOVEMENT_THRESHOLD) return 0 - if(3) - if(n < air_master.AF_NORMAL_MOVEMENT_THRESHOLD) return 0 - if(4,5) - if(n < air_master.AF_LARGE_MOVEMENT_THRESHOLD) return 0 - -proc/Airflow(datum/air_group/A,datum/air_group/B,n,var/list/turf/simulated/target) - //Purpose: AIRFLOW between two airgroups. - //Called by: AIRFLOW - //Inputs: Air group venting, Air group receiving, force of airflow, midpoint turf(s) - //Outputs: None. - - //Now n is a percent of one atm. - n = round((n/air_master.AF_PERCENT_OF)*100,0.1) - - //Don't go any further if n is lower than the lowest value needed for airflow. - if(abs(n) < air_master.AF_TINY_MOVEMENT_THRESHOLD) - return - - if(!target || !target.len) - return - - //Get lists of things that can be thrown across the room for each zone. - var/list/pplz = A.movables() - var/list/otherpplz = B.movables() - - for(var/atom/movable/M in pplz) - - //Check for knocking people over - if(ismob(M) && n > air_master.AF_HUMAN_STUN_THRESHOLD) - if(M:nodamage) continue - M:airflow_stun() - - if(M.check_airflow_movable(n)) - - //Check for things that are in range of the midpoint turfs. - var/fail = 1 - for(var/turf/simulated/T in target) - if(M in range(T)) - fail = 0 - break - if(fail) - continue - - //If they're already being tossed, don't do it again. - if(!M.airflow_speed) - - M.airflow_dest = pick(target) //Pick a random midpoint to fly towards. - - spawn M.GotoAirflowDest(abs(n) * (air_master.AF_SPEED_MULTIPLIER/10)) - //Send the object flying at a speed determined by n and AF_SPEED_MULTIPLIER. - - //Do it again for the stuff in the other zone, making it fly away. - for(var/atom/movable/M in otherpplz) - - if(ismob(M) && abs(n) > air_master.AF_HUMAN_STUN_THRESHOLD) - if(M:nodamage) continue - M:airflow_stun() - - if(M.check_airflow_movable(abs(n))) - - var/fail = 1 - for(var/turf/simulated/T in target) - if(M in range(T)) - fail = 0 - break - if(fail) - continue - - if(M && !M.airflow_speed) - - M.airflow_dest = pick(target) - - spawn M.RepelAirflowDest(abs(n) * (air_master.AF_SPEED_MULTIPLIER/10)) - -proc/AirflowSpace(datum/air_group/A) - //Purpose: AIRFLOW between an airgroup and spess. - //Called by: AIRFLOW - //Inputs: Air group venting into space. - //Outputs: None. - // The space version of the Airflow(A,B,n) proc. - - var/n = A.air.total_moles*air_master.AF_SPACE_MULTIPLIER - //Here, n is determined by the space multiplier constant and the zone's air. - - n = round((n/air_master.AF_PERCENT_OF)*100,0.1) - - if(n < air_master.AF_TINY_MOVEMENT_THRESHOLD) return - - var/list/connected_turfs = A.space_borders //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. - - for(var/atom/movable/M in pplz) - - if(ismob(M) && n > air_master.AF_HUMAN_STUN_THRESHOLD) - if(M:nodamage) continue - M:airflow_stun() - - if(M.check_airflow_movable(n)) - - var/fail = 1 - for(var/turf/U in connected_turfs) - if(M in range(U)) fail = 0 - if(fail) continue - - if(!M.airflow_speed) - M.airflow_dest = pick(connected_turfs) - spawn - if(M) M.GotoAirflowDest(n * (air_master.AF_SPEED_MULTIPLIER/10)) - //Sometimes shit breaks, and M isn't there after the spawn. - -/atom/movable - var/turf/airflow_dest - var/airflow_speed = 0 - var/airflow_time = 0 - - proc/GotoAirflowDest(n) - //Purpose: Moving src between it's current position and where air is dragging them. - //Called by: AIRFLOW - //Inputs: Force. - //Outputs: None. - - if(!airflow_dest) return - if(airflow_speed < 0) return - if(airflow_speed) - airflow_speed = n - return - if(airflow_dest == loc) - step_away(src,loc) - if(ismob(src)) - if(src:nodamage) return - if(istype(src, /mob/living/carbon/human)) - if(istype(src, /mob/living/carbon/human)) - if(src:buckled) return - if(src:wear_suit) - if(src:wear_suit.flags & SUITSPACE) return - if(src:shoes) - if(src:shoes.type == /obj/item/clothing/shoes/magboots && src:shoes.flags & NOSLIP) return - src << "\red You are sucked away by airflow!" - - airflow_speed = min(round(n),9) - airflow_speed /= get_dist(src,airflow_dest) //The further away you are, the less you get dragged. - var - xo = airflow_dest.x - src.x - yo = airflow_dest.y - src.y - od = 0 - airflow_dest = null - if(!density) - density = 1 - od = 1 //It wasn't dense, but it is considered it for when being moved by airflow. - //Main loop to AIRFLOW - while(airflow_speed > 0) - if(airflow_speed <= 0) return - airflow_speed = min(airflow_speed,15) - airflow_speed -= air_master.AF_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 - step_towards(src, src.airflow_dest) - if(ismob(src) && src:client) src:client:move_delay = world.time + 10 - airflow_dest = null - //You cannot be tossed around by airflow more than once ever 1.5(times tick_multiplier) seconds) - airflow_speed = -1 - spawn(150 * tick_multiplier) airflow_speed = 0 - //Reset density. - if(od) - density = 0 - - proc/RepelAirflowDest(n) - //Purpose: Moving src between it's current position and where air is pushing them. - //Called by: AIRFLOW - //Inputs: Force. - //Outputs: None. - - if(!airflow_dest) return - if(airflow_speed < 0) return - if(airflow_speed) - airflow_speed = n - return - if(airflow_dest == loc) - step_away(src,loc) - if(ismob(src)) - if(src:nodamage) return - if(istype(src, /mob/living/carbon/human)) - if(istype(src, /mob/living/carbon/human)) - if(src:buckled) return - if(src:wear_suit) - if(src:wear_suit.flags & SUITSPACE) return - if(src:shoes) - if(src:shoes.type == /obj/item/clothing/shoes/magboots) return - src << "\red You are pushed away by airflow!" - airflow_speed = min(round(n),9) - airflow_speed /= get_dist(src,airflow_dest) //The further away you are, the less you get dragged. - 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 -= air_master.AF_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 - step_towards(src, src.airflow_dest) - if(ismob(src) && src:client) src:client:move_delay = world.time + 10 - airflow_dest = null - airflow_speed = -1 - spawn(150 * tick_multiplier) airflow_speed = 0 - if(od) - density = 0 - - Bump(atom/A) - if(airflow_speed > 0 && airflow_dest) - airflow_hit(A) - else - airflow_speed = 0 - . = ..() - -atom/movable/proc/airflow_hit(atom/A) - //Purpose: Managing impacts between objects whirled around by airflow. - //Called by: AIRFLOW - //Inputs: Object to impact. - //Outputs: None. - - airflow_speed = -1 - spawn(50 * tick_multiplier) airflow_speed = 0 - airflow_dest = null - -mob/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, "smash.ogg", 25, 1, -1) - . = ..() - -obj/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, "smash.ogg", 25, 1, -1) - . = ..() - -obj/item/airflow_hit(atom/A) - airflow_speed = -1 - spawn(50 * tick_multiplier) airflow_speed = 0 - airflow_dest = null - -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) - 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 * air_master.AF_DAMAGE_MULTIPLIER - for(var/organ in src:organs) - var/datum/organ/external/temp = src:organs["[organ]"] - if (istype(temp, /datum/organ/external)) - switch(temp.name) - if("head") - temp.take_damage(b_loss * 0.2, 0) - if("chest") - temp.take_damage(b_loss * 0.4, 0) - if("diaper") - temp.take_damage(b_loss * 0.1, 0) - spawn UpdateDamageIcon() - if(airflow_speed > 10) - paralysis += round(airflow_speed * air_master.AF_STUN_MULTIPLIER) - stunned = max(stunned,paralysis + 3) - else - stunned += round(airflow_speed * air_master.AF_STUN_MULTIPLIER/2) - . = ..() - -/datum/air_group/proc/movables() - //Purpose: Returns everything movable. - //Called by: AIRFLOW - //Inputs: Possible objects to move. - //Outputs: None. - - . = list() - for(var/turf/T in members) - for(var/atom/A in T) - . += A - -proc/Get_Dir(atom/S,atom/T) //Shamelessly stolen from AJX.AdvancedGetDir - var/GDist=get_dist(S,T) - var/GDir=get_dir(S,T) - if(GDist<=3) - if(GDist==0) return 0 - if(GDist==1) - return GDir - - - var/X1=S.x*10 - var/X2=T.x*10 - var/Y1=S.y*10 - var/Y2=T.y*10 - var/Ref - if(GDir==NORTHEAST) - Ref=(X2/X1)*Y1 - if(Ref-1>Y2) .=EAST - else if(Ref+1Y2) .=WEST - else if(Ref+1Y2) .=SOUTH - else if(Ref+1Y2) .=SOUTH - else if(Ref+1> air_master - del F - world.log << "TWEAKS: Airflow, Plasma and Damage settings loaded." \ No newline at end of file diff --git a/code/FEA/FEA_system.dm b/code/FEA/FEA_system.dm index fb7e87ac99c..e8236961bf7 100644 --- a/code/FEA/FEA_system.dm +++ b/code/FEA/FEA_system.dm @@ -54,6 +54,7 @@ Important Procedures */ var/kill_air = 0 +var/tick_multiplier = 2 atom/proc/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) //Purpose: Determines if the object (or airflow) can pass this atom. diff --git a/code/FEA/FEA_variables.dm b/code/FEA/FEA_variables.dm deleted file mode 100644 index 10d75864c67..00000000000 --- a/code/FEA/FEA_variables.dm +++ /dev/null @@ -1,631 +0,0 @@ -//Please note that mose of these variables are holdovers form ZAS, but I really do not want to expend the effort to prune it down quite yet. - -pl_control/var - PLASMA_DMG = 3 - PLASMA_DMG_NAME = "Plasma Damage Multiplier" - PLASMA_DMG_DESC = "Multiplier on how much damage inhaling plasma can do." - - OXY_TO_PLASMA = 1 - OXY_TO_PLASMA_NAME = "O2/Plasma Ratio" - OXY_TO_PLASMA_DESC = "Multiplier for the ratio of oxygen to plasma required in fires." - - CLOTH_CONTAMINATION = 1 //If this is on, plasma does damage by getting into cloth. - CLOTH_CONTAMINATION_NAME = "Plasma - Cloth Contamination" - CLOTH_CONTAMINATION_RANDOM = 60 - CLOTH_CONTAMINATION_METHOD = "Toggle" - CLOTH_CONTAMINATION_DESC = "If set to nonzero, plasma will contaminate cloth items (uniforms, backpacks, etc.)\ - and cause a small amount of damage over time to anyone carrying or wearing them. Contamination can be detected\ - with a Health Analyzer, and washed off in the washer." - - ALL_ITEM_CONTAMINATION = 0 //If this is on, any item can be contaminated, so suits and tools must be discarded or - //decontaminated. - ALL_ITEM_CONTAMINATION_NAME = "Plasma - Full Contamination" - ALL_ITEM_CONTAMINATION_RANDOM = 10 - ALL_ITEM_CONTAMINATION_METHOD = "Toggle" - ALL_ITEM_CONTAMINATION_DESC = "Like Cloth Contamination, but all item types are susceptible." - - PLASMAGUARD_ONLY = 0 - PLASMAGUARD_ONLY_NAME = "Plasma - Biosuits/Spacesuits Only" - PLASMAGUARD_ONLY_RANDOM = 20 - PLASMAGUARD_ONLY_METHOD = "Toggle" - PLASMAGUARD_ONLY_DESC = "If on, any suits that are not biosuits or space suits will not protect against contamination." - - //CANISTER_CORROSION = 0 //If this is on, plasma must be stored in orange tanks and canisters, - //CANISTER_CORROSION_RANDOM = 20 //or it will corrode the tank. - //CANISTER_CORROSION_METHOD = "Toggle" - - GENETIC_CORRUPTION = 0 //Chance of genetic corruption as well as toxic damage, X in 10,000. - GENETIC_CORRUPTION_NAME = "Plasma - Genetic Corruption" - GENETIC_CORRUPTION_RANDOM = "PROB10/3d6" - GENETIC_CORRUPTION_METHOD = "Numeric" - GENETIC_CORRUPTION_DESC = "When set to a probability in 1000, any humans in plasma will have this chance to develop a random mutation." - - SKIN_BURNS = 1 //Plasma has an effect similar to mustard gas on the un-suited. - SKIN_BURNS_NAME = "Plasma - Skin Burns" - SKIN_BURNS_RANDOM = 10 - SKIN_BURNS_METHOD = "Toggle" - SKIN_BURNS_DESC = "When toggled, humans with exposed skin will suffer burns (similar to mustard gas) in plasma." - - //PLASMA_INJECTS_TOXINS = 0 //Plasma damage injects the toxins chemical to do damage over time. - //PLASMA_INJECTS_TOXINS_RANDOM = 30 - //PLASMA_INJECTS_TOXINS_METHOD = "Toggle" - - EYE_BURNS = 0 //Plasma burns the eyes of anyone not wearing eye protection. - EYE_BURNS_NAME = "Plasma - Eye Burns" - EYE_BURNS_RANDOM = 30 - EYE_BURNS_METHOD = "Toggle" - EYE_BURNS_DESC = "When toggled, humans without masks that cover the eyes will suffer temporary blurriness and sight loss,\ - and may need glasses to see again if exposed for long durations." - - //N2O_REACTION = 0 //Plasma can react with N2O, making sparks and starting a fire if levels are high. - //N2O_REACTION_RANDOM = 5 - - //PLASMA_COLOR = "onturf" //Plasma can change colors yaaaay! - //PLASMA_COLOR_RANDOM = "PICKonturf,onturf" - - //PLASMA_DMG_OFFSET = 1 - //PLASMA_DMG_OFFSET_RANDOM = "1d5" - //PLASMA_DMG_QUOTIENT = 10 - //PLASMA_DMG_QUOTIENT_RANDOM = "1d10+4" - - CONTAMINATION_LOSS = 0.1 - _NAME = "Plasma - Contamination Damage" - CONTAMINATION_LOSS_DESC = "A number representing the damage done per life cycle by contaminated items." - - PLASMA_HALLUCINATION = 1 - PLASMA_HALLUCINATION_NAME = "Plasma - Hallucination" - PLASMA_HALLUCINATION_METHOD = "Toggle" - PLASMA_HALLUCINATION_DESC = "If toggled, uses the remnants of the hallucination code to induce visions in those\ - who breathe plasma." - N2O_HALLUCINATION = 1 - N2O_HALLUCINATION_NAME = "Nitrous Oxide - Hallucination" - N2O_HALLUCINATION_METHOD = "Toggle" - N2O_HALLUCINATION_DESC = "If toggled, uses the remnants of the hallucination code to induce visions in those\ - who breathe N2O." - //CONTAMINATION_LOSS_RANDOM = "5d5" -//Plasma has a chance to be a different color. - -var/tick_multiplier = 2 -/datum/controller/air_system/var - //Used in /mob/carbon/human/life - OXYGEN_LOSS = 2 - OXYGEN_LOSS_NAME = "Damage - Oxygen Loss" - OXYGEN_LOSS_DESC = "A multiplier for damage due to lack of air, CO2 poisoning, and vacuum. Does not affect oxyloss\ - from being incapacitated or dying." - TEMP_DMG = 2 - TEMP_DMG_NAME = "Damage - Temperature" - TEMP_DMG_DESC = "A multiplier for damage due to body temperature irregularities." - BURN_DMG = 6 - BURN_DMG_NAME = "Damage - Fire" - BURN_DMG_DESC = "A multiplier for damage due to direct fire exposure." - - AF_TINY_MOVEMENT_THRESHOLD = 50 //% difference to move tiny items. - AF_TINY_MOVEMENT_THRESHOLD_NAME = "Airflow - Tiny Movement Threshold %" - AF_TINY_MOVEMENT_THRESHOLD_DESC = "Percent of 1 Atm. at which items with the tiny weight class will move." - AF_SMALL_MOVEMENT_THRESHOLD = 70 //% difference to move small items. - AF_SMALL_MOVEMENT_THRESHOLD_NAME = "Airflow - Small Movement Threshold %" - AF_SMALL_MOVEMENT_THRESHOLD_DESC = "Percent of 1 Atm. at which items with the small weight class will move." - AF_NORMAL_MOVEMENT_THRESHOLD = 90 //% difference to move normal items. - AF_NORMAL_MOVEMENT_THRESHOLD_NAME = "Airflow - Normal Movement Threshold %" - AF_NORMAL_MOVEMENT_THRESHOLD_DESC = "Percent of 1 Atm. at which items with the normal weight class will move." - AF_LARGE_MOVEMENT_THRESHOLD = 100 //% difference to move large and huge items. - AF_LARGE_MOVEMENT_THRESHOLD_NAME = "Airflow - Large Movement Threshold %" - AF_LARGE_MOVEMENT_THRESHOLD_DESC = "Percent of 1 Atm. at which items with the large or huge weight class will move." - AF_DENSE_MOVEMENT_THRESHOLD = 120 //% difference to move dense crap and mobs. - AF_DENSE_MOVEMENT_THRESHOLD_NAME = "Airflow - Dense Movement Threshold %" - AF_DENSE_MOVEMENT_THRESHOLD_DESC = "Percent of 1 Atm. at which dense objects (canisters, etc.) will be shifted by airflow." - AF_MOB_MOVEMENT_THRESHOLD = 175 - AF_MOB_MOVEMENT_THRESHOLD_NAME = "Airflow - Human Movement Threshold %" - AF_MOB_MOVEMENT_THRESHOLD_DESC = "Percent of 1 Atm. at which mobs will be shifted by airflow." - - AF_HUMAN_STUN_THRESHOLD = 130 - AF_HUMAN_STUN_THRESHOLD_NAME = "Airflow - Human Stun Threshold %" - AF_HUMAN_STUN_THRESHOLD_DESC = "Percent of 1 Atm. at which living things are stunned or knocked over." - - AF_PERCENT_OF = ONE_ATMOSPHERE - AF_PERCENT_OF_NAME = "Airflow - 100% Pressure" - AF_PERCENT_OF_DESC = "Normally set to 1 Atm. in kPa, this indicates what pressure is considered 100% by the system." - - AF_SPEED_MULTIPLIER = 4 //airspeed per movement threshold value crossed. - AF_SPEED_MULTIPLIER_NAME = "Airflow - Speed Increase per 10%" - AF_SPEED_MULTIPLIER_DESC = "Velocity increase of shifted items per 10% of airflow." - AF_DAMAGE_MULTIPLIER = 5 //Amount of damage applied per airflow_speed. - AF_DAMAGE_MULTIPLIER_NAME = "Airflow - Damage Per Velocity" - AF_DAMAGE_MULTIPLIER_DESC = "Amount of damage applied per unit of speed (1-15 units) at which mobs are thrown." - AF_STUN_MULTIPLIER = 1.5 //Seconds of stun applied per airflow_speed. - AF_STUN_MULTIPLIER_NAME = "Airflow - Stun Per Velocity" - AF_STUN_MULTIPLIER_DESC = "Amount of stun effect applied per unit of speed (1-15 units) at which mobs are thrown." - AF_SPEED_DECAY = 0.5 //Amount that flow speed will decay with time. - AF_SPEED_DECAY_NAME = "Airflow - Velocity Lost per Tick" - AF_SPEED_DECAY_DESC = "Amount of airflow speed lost per tick on a moving object." - AF_SPACE_MULTIPLIER = 2 //Increasing this will make space connections more DRAMATIC! - AF_SPACE_MULTIPLIER_NAME = "Airflow - Space Airflow Multiplier" - AF_SPACE_MULTIPLIER_DESC = "Increasing this multiplier will cause more powerful airflow to space." - AF_CANISTER_MULTIPLIER = 0.25 - AF_CANISTER_MULTIPLIER_NAME = "Airflow - Canister Airflow Multiplier" - AF_CANISTER_MULTIPLIER_DESC = "Increasing this multiplier will cause more powerful airflow from single-tile sources like canisters." - -/datum/controller/air_system - var - list/settings = list() - list/bitflags = list("1","2","4","8","16","32","64","128","256","512","1024") - pl_control/plc = new() - 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 - - 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 plc.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) - var/vw - var/how = "Text" - if(ch in plc.settings) - vw = plc.vars[ch] - if("[ch]_METHOD" in vars) - how = plc.vars["[ch]_METHOD"] - else - if(isnum(vw)) - how = "Numeric" - else - how = "Text" - else - vw = vars[ch] - if("[ch]_METHOD" in vars) - how = vars["[ch]_METHOD"] - 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 - else - vars[ch] = vw - if(how == "Toggle") - newvar = (newvar?"ON":"OFF") - world << "\blue [key_name(user)] changed the setting [ch] to [newvar]." - //user << "[which] has been changed 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 - - proc/ChangePlasma() - for(var/V in plc.settings) - plc.Randomize(V) - ////world << "Plasma randomized." - - proc/SetDefault(def) - switch(def) - if("Original") - plc.CLOTH_CONTAMINATION = 0 //If this is on, plasma does damage by getting into cloth. - - plc.ALL_ITEM_CONTAMINATION = 0 //If this is on, any item can be contaminated, so suits and tools must be discarded or - - plc.PLASMAGUARD_ONLY = 0 - - //plc.CANISTER_CORROSION = 0 //If this is on, plasma must be stored in orange tanks and canisters, - - 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.PLASMA_INJECTS_TOXINS = 0 //Plasma damage injects the toxins chemical to do damage over time. - - plc.EYE_BURNS = 0 //Plasma burns the eyes of anyone not wearing eye protection. - - //plc.N2O_REACTION = 0 //Plasma can react with N2O, making sparks and starting a fire if levels are high. - - //plc.PLASMA_COLOR = "onturf" //Plasma can change colors yaaaay! - - //plc.PLASMA_DMG_OFFSET = 1 - //plc.PLASMA_DMG_QUOTIENT = 10 - - plc.CONTAMINATION_LOSS = 0 - if("Hazard-Low") - plc.CLOTH_CONTAMINATION = 1 //If this is on, plasma does damage by getting into cloth. - - plc.ALL_ITEM_CONTAMINATION = 0 //If this is on, any item can be contaminated, so suits and tools must be discarded or - - plc.PLASMAGUARD_ONLY = 0 - - // plc.CANISTER_CORROSION = 0 //If this is on, plasma must be stored in orange tanks and canisters, - - 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.PLASMA_INJECTS_TOXINS = 0 //Plasma damage injects the toxins chemical to do damage over time. - - plc.EYE_BURNS = 0 //Plasma burns the eyes of anyone not wearing eye protection. - - // plc.N2O_REACTION = 0 //Plasma can react with N2O, making sparks and starting a fire if levels are high. - - // plc.PLASMA_COLOR = "onturf" //RBPYB - - //if(prob(20)) - // plc.PLASMA_COLOR = pick("red","yellow","blue","purple") - - //plc.PLASMA_DMG_OFFSET = 1.5 - //plc.PLASMA_DMG_QUOTIENT = 8 - - plc.CONTAMINATION_LOSS = 0.01 - - var/s = pick(plc.settings) - plc.Randomize(s) - - if("Hazard-High") - plc.CLOTH_CONTAMINATION = 1 //If this is on, plasma does damage by getting into cloth. - - plc.ALL_ITEM_CONTAMINATION = 0 //If this is on, any item can be contaminated, so suits and tools must be discarded or - - plc.PLASMAGUARD_ONLY = 0 - - // plc.CANISTER_CORROSION = 1 //If this is on, plasma must be stored in orange tanks and canisters, - - 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.PLASMA_INJECTS_TOXINS = 0 //Plasma damage injects the toxins chemical to do damage over time. - - plc.EYE_BURNS = 0 //Plasma burns the eyes of anyone not wearing eye protection. - - // plc.N2O_REACTION = 0 //Plasma can react with N2O, making sparks and starting a fire if levels are high. - - // plc.PLASMA_COLOR = "onturf"//pick("red","yellow","blue","purple") //RBPYB - - //plc.PLASMA_DMG_OFFSET = 3 - //plc.PLASMA_DMG_QUOTIENT = 5 - - plc.CONTAMINATION_LOSS = 0.05 - - for(var/i = rand(3,5),i>0,i--) - var/s = pick(plc.settings) - plc.Randomize(s) - - if("Everything") - plc.CLOTH_CONTAMINATION = 1 //If this is on, plasma does damage by getting into cloth. - - plc.ALL_ITEM_CONTAMINATION = 1 //If this is on, any item can be contaminated, so suits and tools must be discarded or ELSE - - plc.PLASMAGUARD_ONLY = 1 - - // plc.CANISTER_CORROSION = 1 //If this is on, plasma must be stored in orange tanks and canisters, - - 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.PLASMA_INJECTS_TOXINS = 1 //Plasma damage injects the toxins chemical to do damage over time. - - plc.EYE_BURNS = 1 //Plasma burns the eyes of anyone not wearing eye protection. - - // plc.N2O_REACTION = 1 //Plasma can react with N2O, making sparks and starting a fire if levels are high. - - // plc.PLASMA_COLOR = "onturf" //RBPYB - - //plc.PLASMA_DMG_OFFSET = 3 - //plc.PLASMA_DMG_QUOTIENT = 5 - - plc.CONTAMINATION_LOSS = 0.02 - /////world << "Plasma color updated." - -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) - //world << "Randomizing [V]" - var/newvalue - if("[V]_RANDOM" in vars) - if(isnum(vars["[V]_RANDOM"])) - newvalue = prob(vars["[V]_RANDOM"]) - if(newvalue) - //world << "Probability [vars["[V]_RANDOM"]]%: Success." - else - //world << "Probability [vars["[V]_RANDOM"]]%: Failure." - else if(istext(vars["[V]_RANDOM"])) - var/txt = vars["[V]_RANDOM"] - if(findtextEx(txt,"PROB")) - //world << "Probability/Roll Combo \..." - txt = dd_text2list(txt,"/") - txt[1] = dd_replacetext(txt[1],"PROB","") - var/p = text2num(txt[1]) - var/r = txt[2] - //world << "Prob:[p]% Roll:[r]" - if(prob(p)) - newvalue = roll(r) - //world << "Success. New value: [newvalue]" - else - newvalue = vars[V] - //world << "Probability check failed." - else if(findtextEx(txt,"PICK")) - txt = dd_replacetext(txt,"PICK","") - //world << "Pick: [txt]" - txt = dd_text2list(txt,",") - newvalue = pick(txt) - //world << "Picked: [newvalue]" - else - newvalue = roll(txt) - //world << "Roll: [txt] - [newvalue]" - else - newvalue = vars[V] - vars[V] = newvalue - ////world << "Plasma color updated." - -mob/proc/Change_Airflow_Constants() - set category = "Debug" - - var/choice = input("Which constant will you modify?","Change Airflow Constants")\ - as null|anything in list("Movement Threshold","Speed Multiplier","Damage Multiplier","Stun Multiplier","Speed Decay") - - var/n - - switch(choice) - if("Movement Threshold") - n = input("What will you change it to","Change Airflow Constants",air_master.AF_DENSE_MOVEMENT_THRESHOLD) as num - n = max(1,n) - air_master.AF_DENSE_MOVEMENT_THRESHOLD = n - world.log << "air_master.AF_DENSE_MOVEMENT_THRESHOLD set to [n]." - if("Speed Multiplier") - n = input("What will you change it to","Change Airflow Constants",air_master.AF_SPEED_MULTIPLIER) as num - n = max(1,n) - air_master.AF_SPEED_MULTIPLIER = n - world.log << "air_master.AF_SPEED_MULTIPLIER set to [n]." - if("Damage Multiplier") - n = input("What will you change it to","Change Airflow Constants",air_master.AF_DAMAGE_MULTIPLIER) as num - air_master.AF_DAMAGE_MULTIPLIER = n - world.log << "AF_DAMAGE_MULTIPLIER set to [n]." - if("Stun Multiplier") - n = input("What will you change it to","Change Airflow Constants",air_master.AF_STUN_MULTIPLIER) as num - air_master.AF_STUN_MULTIPLIER = n - world.log << "AF_STUN_MULTIPLIER set to [n]." - if("Speed Decay") - n = input("What will you change it to","Change Airflow Constants",air_master.AF_SPEED_DECAY) as num - air_master.AF_SPEED_DECAY = n - world.log << "AF_SPEED_DECAY set to [n]." - if("Space Flow Multiplier") - n = input("What will you change it to","Change Airflow Constants",air_master.AF_SPEED_DECAY) as num - air_master.AF_SPEED_DECAY = n - world.log << "AF_SPEED_DECAY set to [n]." - -obj/var/contaminated = 0 - -obj/item/proc - can_contaminate() - if(flags & PLASMAGUARD) return 0 - if((flags & SUITSPACE) && !air_master.plc.PLASMAGUARD_ONLY) return 1 - if(air_master.plc.ALL_ITEM_CONTAMINATION) return 1 - else if(istype(src,/obj/item/clothing)) return 1 - else if(istype(src,/obj/item/weapon/storage/backpack)) return 1 - -/mob/living/carbon/human/proc/contaminate() - if(!pl_suit_protected()) - suit_contamination() - else if(air_master.plc.PLASMAGUARD_ONLY) - if(!wear_suit.flags & PLASMAGUARD) wear_suit.contaminated = 1 - - - - if(!pl_head_protected()) - if(wear_mask) wear_mask.contaminated = 1 - if(prob(1)) suit_contamination() //Plasma can sometimes get through such an open suit. - else if(air_master.plc.PLASMAGUARD_ONLY) - if(!head.flags & PLASMAGUARD) head.contaminated = 1 - - if(istype(back,/obj/item/weapon/storage/backpack) || air_master.plc.ALL_ITEM_CONTAMINATION) - back.contaminated = 1 - - if(l_hand) - if(l_hand.can_contaminate()) l_hand.contaminated = 1 - if(r_hand) - if(r_hand.can_contaminate()) r_hand.contaminated = 1 - if(belt) - if(belt.can_contaminate()) belt.contaminated = 1 - if(wear_id && !pl_suit_protected()) - if(wear_id.can_contaminate()) wear_id.contaminated = 1 - if(l_ear && !pl_head_protected()) - if(l_ear.can_contaminate()) l_ear.contaminated = 1 - if(r_ear && !pl_head_protected()) - if(r_ear.can_contaminate()) r_ear.contaminated = 1 - -/mob/living/carbon/human/proc/pl_effects() - if(stat >= 2) - return - if(air_master.plc.SKIN_BURNS) - if(!pl_head_protected() || !pl_suit_protected()) - burn_skin(0.75) - if (coughedtime != 1) - coughedtime = 1 - emote("gasp") - spawn (20) - coughedtime = 0 - updatehealth() - if(air_master.plc.EYE_BURNS && !pl_head_protected()) - if(!wear_mask) - if(prob(20)) usr << "\red Your eyes burn!" - eye_stat += 2.5 - eye_blurry += 1.5 - if (eye_stat >= 20 && !(disabilities & 1)) - src << "\red Your eyes start to burn badly!" - disabilities |= 1 - if (prob(max(0,eye_stat - 20) + 1)) - src << "\red You are blinded!" - eye_blind += 20 - eye_stat = max(eye_stat-25,0) - else - if(!(wear_mask.flags & MASKCOVERSEYES)) - if(prob(20)) usr << "\red Your eyes burn!" - eye_stat += 2.5 - eye_blurry = min(eye_blurry+1.5,50) - if (eye_stat >= 20 && !(disabilities & 1)) - src << "\red Your eyes start to burn badly!" - disabilities |= 1 - if (prob(max(0,eye_stat - 20) + 1) &&!eye_blind) - src << "\red You are blinded!" - eye_blind += 20 - eye_stat = 0 - if(air_master.plc.GENETIC_CORRUPTION) - if(rand(1,1000) < air_master.plc.GENETIC_CORRUPTION) - randmutb(src) - src << "\red High levels of toxins cause you to spontaneously mutate." - domutcheck(src,null) - -/mob/living/carbon/human/proc/FireBurn(mx as num) - //NO! NOT INTO THE PIT! IT BURRRRRNS! - mx *= air_master.BURN_DMG - - var - head_exposure = 1 - chest_exposure = 1 - groin_exposure = 1 - legs_exposure = 1 - feet_exposure = 1 - arms_exposure = 1 - hands_exposure = 1 - for(var/obj/item/clothing/C in src) - if(l_hand == C || r_hand == C) continue - if(C.body_parts_covered & HEAD) - head_exposure *= C.heat_transfer_coefficient - if(C.body_parts_covered & UPPER_TORSO) - chest_exposure *= C.heat_transfer_coefficient - if(C.body_parts_covered & LOWER_TORSO) - groin_exposure *= C.heat_transfer_coefficient - if(C.body_parts_covered & LEGS) - legs_exposure *= C.heat_transfer_coefficient - if(C.body_parts_covered & FEET) - feet_exposure *= C.heat_transfer_coefficient - if(C.body_parts_covered & ARMS) - arms_exposure *= C.heat_transfer_coefficient - if(C.body_parts_covered & HANDS) - arms_exposure *= C.heat_transfer_coefficient - - mx *= 10 - - apply_damage("head", 0, 2.5*mx*head_exposure) - apply_damage("chest", 0, 2.5*mx*chest_exposure) - apply_damage("groin", 0, 2.0*mx*groin_exposure) - apply_damage("l_leg", 0, 0.6*mx*legs_exposure) - apply_damage("r_leg", 0, 0.6*mx*legs_exposure) - apply_damage("l_arm", 0, 0.4*mx*arms_exposure) - apply_damage("r_arm", 0, 0.4*mx*arms_exposure) - apply_damage("l_foot", 0, 0.25*mx*feet_exposure) - apply_damage("r_foot", 0, 0.25*mx*feet_exposure) - apply_damage("l_hand", 0, 0.25*mx*hands_exposure) - apply_damage("r_hand", 0, 0.25*mx*hands_exposure) - -/mob/living/carbon/human/proc/suit_interior() - . = list() - if(!pl_suit_protected()) - for(var/obj/item/I in src) - . += I - return . - . += wear_mask - . += w_uniform - . += shoes - . += gloves - if(!pl_head_protected()) - . += head - -/mob/living/carbon/human/proc/pl_head_protected() - if(head) - if(head.flags & PLASMAGUARD || head.flags & HEADSPACE) return 1 - return 0 - -/mob/living/carbon/human/proc/pl_suit_protected() - if(wear_suit) - if(wear_suit.flags & PLASMAGUARD || wear_suit.flags & SUITSPACE) return 1 - return 0 - -/mob/living/carbon/human/proc/suit_contamination() - if(air_master.plc.ALL_ITEM_CONTAMINATION) - for(var/obj/item/I in src) - I.contaminated = 1 - else - if(wear_suit) wear_suit.contaminated = 1 - if(w_uniform) w_uniform.contaminated = 1 - if(shoes) shoes.contaminated = 1 - if(gloves) gloves.contaminated = 1 - if(wear_mask) wear_mask.contaminated = 1 - - -turf/Entered(obj/item/I) - . = ..() - if(istype(I)) - var/datum/gas_mixture/env = return_air(1) - if(env.toxins > 0.35) - if(I.can_contaminate()) - I.contaminated = 1 \ No newline at end of file diff --git a/code/WorkInProgress/Cael_Aislinn/Supermatter/SuperMatter.dm b/code/WorkInProgress/Cael_Aislinn/Supermatter/SuperMatter.dm index 5661f8d212d..ebbf265ca31 100644 --- a/code/WorkInProgress/Cael_Aislinn/Supermatter/SuperMatter.dm +++ b/code/WorkInProgress/Cael_Aislinn/Supermatter/SuperMatter.dm @@ -60,12 +60,6 @@ //a lot of these variables are pretty hacked, so dont rely on the comments /obj/machinery/power/supermatter/process() - var/datum/gas_mixture/env = loc.return_air() - - //Remove gas from surrounding area - var/transfer_moles = gasefficency * env.total_moles - var/datum/gas_mixture/removed = env.remove(transfer_moles) - //core can no longer spontaneously explode /* previousdet = det diff --git a/code/game/master_controller.dm b/code/game/master_controller.dm index 754903fe8d7..dcd8969b6bb 100644 --- a/code/game/master_controller.dm +++ b/code/game/master_controller.dm @@ -137,7 +137,7 @@ datum/controller/game_controller spawn(0) - air_master.process() +// air_master.process() air_master_ready = 1 spawn(0) tension_master.process() diff --git a/code/game/vehicles/airtight/airtight.dm b/code/game/vehicles/airtight/airtight.dm index 44ee0fff2b4..27a8cde7184 100644 --- a/code/game/vehicles/airtight/airtight.dm +++ b/code/game/vehicles/airtight/airtight.dm @@ -46,7 +46,7 @@ delay = 20 process(var/obj/vehicle/airtight/V) - if(V.cabin_air && V.cabin_air.return_volume() > 0) + if(V.cabin_air && V.cabin_air.volume > 0) var/delta = V.cabin_air.temperature - T20C V.cabin_air.temperature -= max(-10, min(10, round(delta/4,0.1))) return @@ -65,8 +65,8 @@ var/pressure_delta = min(release_pressure - cabin_pressure, (tank_air.return_pressure() - cabin_pressure)/2) var/transfer_moles = 0 if(pressure_delta > 0) //cabin pressure lower than release pressure - if(tank_air.return_temperature() > 0) - transfer_moles = pressure_delta*cabin_air.return_volume()/(cabin_air.return_temperature() * R_IDEAL_GAS_EQUATION) + if(tank_air.temperature > 0) + transfer_moles = pressure_delta*cabin_air.volume/(cabin_air.temperature * R_IDEAL_GAS_EQUATION) var/datum/gas_mixture/removed = tank_air.remove(transfer_moles) cabin_air.merge(removed) else if(pressure_delta < 0) //cabin pressure higher than release pressure @@ -75,7 +75,7 @@ if(t_air) pressure_delta = min(cabin_pressure - t_air.return_pressure(), pressure_delta) if(pressure_delta > 0) //if location pressure is lower than cabin pressure - transfer_moles = pressure_delta*cabin_air.return_volume()/(cabin_air.return_temperature() * R_IDEAL_GAS_EQUATION) + transfer_moles = pressure_delta*cabin_air.volume/(cabin_air.temperature * R_IDEAL_GAS_EQUATION) var/datum/gas_mixture/removed = cabin_air.remove(transfer_moles) if(t_air) t_air.merge(removed) @@ -123,11 +123,11 @@ /obj/vehicle/airtight/proc/return_temperature() . = 0 if(use_internal_tank) - . = cabin_air.return_temperature() + . = cabin_air.temperature else var/datum/gas_mixture/t_air = get_turf_air() if(t_air) - . = t_air.return_temperature() + . = t_air.temperature return /obj/vehicle/airtight/proc/connect(obj/machinery/atmospherics/portables_connector/new_port) diff --git a/code/game/vehicles/vehicle.dm b/code/game/vehicles/vehicle.dm index 87d40b69303..c83a391a310 100644 --- a/code/game/vehicles/vehicle.dm +++ b/code/game/vehicles/vehicle.dm @@ -166,12 +166,12 @@ if(mecha.internal_tank.return_pressure()>mecha.internal_tank.maximum_pressure && !(mecha.hasInternalDamage(MECHA_INT_TANK_BREACH))) mecha.setInternalDamage(MECHA_INT_TANK_BREACH) var/datum/gas_mixture/int_tank_air = mecha.internal_tank.return_air() - if(int_tank_air && int_tank_air.return_volume()>0) //heat the air_contents + if(int_tank_air && int_tank_air.volume>0) //heat the air_contents int_tank_air.temperature = min(6000+T0C, int_tank_air.temperature+rand(10,15)) - if(mecha.cabin_air && mecha.cabin_air.return_volume()>0) - mecha.cabin_air.temperature = min(6000+T0C, mecha.cabin_air.return_temperature()+rand(10,15)) - if(mecha.cabin_air.return_temperature()>mecha.max_temperature/2) - mecha.take_damage(4/round(mecha.max_temperature/mecha.cabin_air.return_temperature(),0.1),"fire") + if(mecha.cabin_air && mecha.cabin_air.volume>0) + mecha.cabin_air.temperature = min(6000+T0C, mecha.cabin_air.temperature+rand(10,15)) + if(mecha.cabin_air.temperature>mecha.max_temperature/2) + mecha.take_damage(4/round(mecha.max_temperature/mecha.cabin_air.temperature,0.1),"fire") if(mecha.hasInternalDamage(MECHA_INT_TEMP_CONTROL)) //stop the mecha_preserve_temp loop datum mecha.pr_int_temp_processor.stop() if(mecha.hasInternalDamage(MECHA_INT_TANK_BREACH)) //remove some air from internal tank diff --git a/code/modules/admin/verbs/diagnostics.dm b/code/modules/admin/verbs/diagnostics.dm index 80897df1c35..fa68b836d90 100644 --- a/code/modules/admin/verbs/diagnostics.dm +++ b/code/modules/admin/verbs/diagnostics.dm @@ -217,7 +217,6 @@ var/turf/T = get_turf(usr) if(istype(T, /turf/simulated)) var/datum/air_group/AG = T:parent - AG.next_check = 30 AG.group_processing = 0 else usr << "Local airgroup is unsimulated!"