diff --git a/code/WorkInProgress/virus2/dishincubator.dm b/code/WorkInProgress/virus2/dishincubator.dm
new file mode 100644
index 0000000000..97ed581148
--- /dev/null
+++ b/code/WorkInProgress/virus2/dishincubator.dm
@@ -0,0 +1,169 @@
+/obj/machinery/disease2/incubator/
+ name = "Pathogenic incubator"
+ density = 1
+ anchored = 1
+ icon = 'virology.dmi'
+ icon_state = "incubator"
+ var/obj/item/weapon/virusdish/dish
+ var/obj/item/weapon/reagent_containers/glass/beaker = null
+ var/radiation = 0
+
+ var/on = 0
+ var/power = 0
+
+ var/foodsupply = 0
+ var/toxins = 0
+
+ ex_act(severity)
+ switch(severity)
+ if(1.0)
+ del(src)
+ return
+ if(2.0)
+ if (prob(50))
+ del(src)
+ return
+
+ blob_act()
+ if (prob(25))
+ del(src)
+
+ meteorhit()
+ del(src)
+ return
+
+ attackby(var/obj/B as obj, var/mob/user as mob)
+ if(istype(B, /obj/item/weapon/reagent_containers/glass) || istype(B,/obj/item/weapon/reagent_containers/syringe))
+
+ if(src.beaker)
+ if(istype(beaker,/obj/item/weapon/reagent_containers/syringe))
+ user << "A syringe is already loaded into the machine."
+ else
+ user << "A beaker is already loaded into the machine."
+ return
+
+ src.beaker = B
+ user.drop_item()
+ B.loc = src
+ if(istype(B,/obj/item/weapon/reagent_containers/syringe))
+ user << "You add the syringe to the machine!"
+ src.updateUsrDialog()
+ else
+ user << "You add the beaker to the machine!"
+ src.updateUsrDialog()
+ else
+ if(istype(B,/obj/item/weapon/virusdish))
+ if(src.dish)
+ user << "A dish is already loaded into the machine."
+ return
+
+ src.dish = B
+ user.drop_item()
+ B.loc = src
+ if(istype(B,/obj/item/weapon/virusdish))
+ user << "You add the dish to the machine!"
+ src.updateUsrDialog()
+
+ Topic(href, href_list)
+ if(stat & BROKEN) return
+ if(usr.stat || usr.restrained()) return
+ if(!in_range(src, usr)) return
+ if (href_list["ejectchem"])
+ if(beaker)
+ beaker.loc = src.loc
+ beaker = null
+ if(!dish)
+ return
+ usr.machine = src
+ if (href_list["power"])
+ on = !on
+ if(on)
+ icon_state = "incubator_on"
+ else
+ icon_state = "incubator"
+ if (href_list["ejectdish"])
+ if(dish)
+ dish.loc = src.loc
+ dish = null
+ if (href_list["rad"])
+ radiation += 10
+ if (href_list["flush"])
+ radiation = 0
+ toxins = 0
+ foodsupply = 0
+
+
+ src.add_fingerprint(usr)
+ src.updateUsrDialog()
+
+ attack_hand(mob/user as mob)
+ if(stat & BROKEN)
+ return
+ user.machine = src
+ var/dat = ""
+ if(!dish)
+ dat = "Please insert dish into the incubator.
"
+ var/string = "Off"
+ if(on)
+ string = "On"
+ dat += "Power status : [string]"
+ dat += "
"
+ dat += "Food supply : [foodsupply]"
+ dat += "
"
+ dat += "Radiation Levels : [radiation] RADS : Radiate"
+ dat += "
"
+ dat += "Toxins : [toxins]"
+ dat += "
"
+ if(beaker)
+ dat += "Eject chemicals : Eject"
+ dat += "
"
+ if(dish)
+ dat += "Eject Virus dish : Eject"
+ dat += "
"
+ dat += "
"
+ dat += "Flush system
"
+ dat += "Close
"
+ user << browse("
Pathogenic incubatorincubator menu:
[dat]", "window=incubator;size=575x400")
+ onclose(user, "incubator")
+ return
+
+
+
+
+ process()
+
+ if(dish && on && dish.virus2)
+ use_power(50,EQUIP)
+ if(!powered(EQUIP))
+ on = 0
+ icon_state = "incubator"
+ if(foodsupply)
+ foodsupply -= 1
+ dish.growth += 3
+ if(dish.growth >= 100)
+ state("The [src.name] pings", "blue")
+ if(radiation)
+ if(radiation > 50 & prob(5))
+ dish.virus2.majormutate()
+ if(dish.info)
+ dish.info = "OUTDATED : [dish.info]"
+ dish.analysed = 0
+ state("The [src.name] beeps", "blue")
+
+ else if(prob(5))
+ dish.virus2.minormutate()
+ radiation -= 1
+ if(toxins && prob(5))
+ dish.virus2.infectionchance -= 1
+ if(toxins > 50)
+ dish.virus2 = null
+ else if(!dish)
+ on = 0
+ icon_state = "incubator"
+
+
+ if(beaker)
+ if(!beaker.reagents.remove_reagent("virusfood",5))
+ foodsupply += 10
+ if(!beaker.reagents.remove_reagent("toxin",1))
+ toxins += 1
\ No newline at end of file
diff --git a/code/ZAS/Airflow.dm b/code/ZAS/Airflow.dm
index a2506bb2d9..3fd0c372bc 100644
--- a/code/ZAS/Airflow.dm
+++ b/code/ZAS/Airflow.dm
@@ -225,142 +225,142 @@ proc/AirflowSpace(zone/A)
if(M) M.GotoAirflowDest(n/10)
//Sometimes shit breaks, and M isn't there after the spawn.
-atom/movable
- var/tmp/turf/airflow_dest
- var/tmp/airflow_speed = 0
- var/tmp/airflow_time = 0
- var/tmp/last_airflow = 0
- proc/GotoAirflowDest(n)
- if(!airflow_dest) return
- if(airflow_speed < 0) return
- if(last_airflow > world.time - vsc.airflow_delay) return
- if(airflow_speed)
- airflow_speed = n/max(get_dist(src,airflow_dest),1)
+/atom/movable/var/tmp/turf/airflow_dest
+/atom/movable/var/tmp/airflow_speed = 0
+/atom/movable/var/tmp/airflow_time = 0
+/atom/movable/var/tmp/last_airflow = 0
+
+/atom/movable/proc/GotoAirflowDest(n)
+ if(!airflow_dest) return
+ if(airflow_speed < 0) return
+ if(last_airflow > world.time - vsc.airflow_delay) return
+ if(airflow_speed)
+ airflow_speed = n/max(get_dist(src,airflow_dest),1)
+ return
+ last_airflow = world.time
+ if(airflow_dest == loc)
+ step_away(src,loc)
+ if(ismob(src))
+ if(src:status_flags & GODMODE)
return
- last_airflow = world.time
- if(airflow_dest == loc)
- step_away(src,loc)
- if(ismob(src))
- if(src:status_flags & GODMODE)
+ if(istype(src, /mob/living/carbon/human))
+ if(src:buckled)
return
- if(istype(src, /mob/living/carbon/human))
- if(src:buckled)
- return
- if(src:shoes)
- if(istype(src:shoes, /obj/item/clothing/shoes/magboots))
- if(src:shoes:magpulse)
- return
- src << "\red You are sucked away by airflow!"
- var/airflow_falloff = 9 - ul_FalloffAmount(airflow_dest) //It's a fast falloff calc. Very useful.
- if(airflow_falloff < 1)
- airflow_dest = null
- return
- airflow_speed = min(max(n * (9/airflow_falloff),1),9)
- var
- xo = airflow_dest.x - src.x
- yo = airflow_dest.y - src.y
- od = 0
+ if(src:shoes)
+ if(istype(src:shoes, /obj/item/clothing/shoes/magboots))
+ if(src:shoes:magpulse)
+ return
+ src << "\red You are sucked away by airflow!"
+ var/airflow_falloff = 9 - ul_FalloffAmount(airflow_dest) //It's a fast falloff calc. Very useful.
+ if(airflow_falloff < 1)
airflow_dest = null
- if(!density)
- density = 1
- od = 1
- while(airflow_speed > 0)
- if(airflow_speed <= 0) return
- airflow_speed = min(airflow_speed,15)
- airflow_speed -= vsc.airflow_speed_decay
- if(airflow_speed > 7)
- if(airflow_time++ >= airflow_speed - 7)
- if(od)
- density = 0
- sleep(1 * tick_multiplier)
- else
+ return
+ airflow_speed = min(max(n * (9/airflow_falloff),1),9)
+ var
+ xo = airflow_dest.x - src.x
+ yo = airflow_dest.y - src.y
+ od = 0
+ airflow_dest = null
+ if(!density)
+ density = 1
+ od = 1
+ while(airflow_speed > 0)
+ if(airflow_speed <= 0) return
+ airflow_speed = min(airflow_speed,15)
+ airflow_speed -= vsc.airflow_speed_decay
+ if(airflow_speed > 7)
+ if(airflow_time++ >= airflow_speed - 7)
if(od)
density = 0
- sleep(max(1,10-(airflow_speed+3)) * tick_multiplier)
- if(od)
- density = 1
- if ((!( src.airflow_dest ) || src.loc == src.airflow_dest))
- src.airflow_dest = locate(min(max(src.x + xo, 1), world.maxx), min(max(src.y + yo, 1), world.maxy), src.z)
- if ((src.x == 1 || src.x == world.maxx || src.y == 1 || src.y == world.maxy))
- return
- if(!istype(loc, /turf))
- return
- step_towards(src, src.airflow_dest)
- if(ismob(src) && src:client)
- src:client:move_delay = world.time + vsc.airflow_mob_slowdown
- airflow_dest = null
- airflow_speed = 0
- airflow_time = 0
- if(od)
- density = 0
-
-
- proc/RepelAirflowDest(n)
- if(!airflow_dest) return
- if(airflow_speed < 0) return
- if(last_airflow > world.time - vsc.airflow_delay) return
- if(airflow_speed)
- airflow_speed = n/max(get_dist(src,airflow_dest),1)
- return
- if(airflow_dest == loc)
- step_away(src,loc)
- if(ismob(src))
- if(src:status_flags & GODMODE)
- return
- if(istype(src, /mob/living/carbon/human))
- if(src:buckled)
- return
- if(src:shoes)
- if(src:shoes.type == /obj/item/clothing/shoes/magboots)
- if(src:shoes.flags & NOSLIP)
- return
- src << "\red You are pushed away by airflow!"
- last_airflow = world.time
- var/airflow_falloff = 9 - ul_FalloffAmount(airflow_dest) //It's a fast falloff calc. Very useful.
- if(airflow_falloff < 1)
- airflow_dest = null
- return
- airflow_speed = min(max(n * (9/airflow_falloff),1),9)
- var
- xo = -(airflow_dest.x - src.x)
- yo = -(airflow_dest.y - src.y)
- od = 0
- airflow_dest = null
- if(!density)
- density = 1
- od = 1
- while(airflow_speed > 0)
- if(airflow_speed <= 0) return
- airflow_speed = min(airflow_speed,15)
- airflow_speed -= vsc.airflow_speed_decay
- if(airflow_speed > 7)
- if(airflow_time++ >= airflow_speed - 7)
- sleep(1 * tick_multiplier)
- else
- sleep(max(1,10-(airflow_speed+3)) * tick_multiplier)
- if ((!( src.airflow_dest ) || src.loc == src.airflow_dest))
- src.airflow_dest = locate(min(max(src.x + xo, 1), world.maxx), min(max(src.y + yo, 1), world.maxy), src.z)
- if ((src.x == 1 || src.x == world.maxx || src.y == 1 || src.y == world.maxy))
- return
- if(!istype(loc, /turf))
- return
- step_towards(src, src.airflow_dest)
- if(ismob(src) && src:client)
- src:client:move_delay = world.time + vsc.airflow_mob_slowdown
- airflow_dest = null
- airflow_speed = 0
- airflow_time = 0
- if(od)
- density = 0
-
- Bump(atom/A)
- if(airflow_speed > 0 && airflow_dest)
- airflow_hit(A)
+ sleep(1 * tick_multiplier)
else
- airflow_speed = 0
- airflow_time = 0
- . = ..()
+ if(od)
+ density = 0
+ sleep(max(1,10-(airflow_speed+3)) * tick_multiplier)
+ if(od)
+ density = 1
+ if ((!( src.airflow_dest ) || src.loc == src.airflow_dest))
+ src.airflow_dest = locate(min(max(src.x + xo, 1), world.maxx), min(max(src.y + yo, 1), world.maxy), src.z)
+ if ((src.x == 1 || src.x == world.maxx || src.y == 1 || src.y == world.maxy))
+ return
+ if(!istype(loc, /turf))
+ return
+ step_towards(src, src.airflow_dest)
+ if(ismob(src) && src:client)
+ src:client:move_delay = world.time + vsc.airflow_mob_slowdown
+ airflow_dest = null
+ airflow_speed = 0
+ airflow_time = 0
+ if(od)
+ density = 0
+
+
+/atom/movable/proc/RepelAirflowDest(n)
+ if(!airflow_dest) return
+ if(airflow_speed < 0) return
+ if(last_airflow > world.time - vsc.airflow_delay) return
+ if(airflow_speed)
+ airflow_speed = n/max(get_dist(src,airflow_dest),1)
+ return
+ if(airflow_dest == loc)
+ step_away(src,loc)
+ if(ismob(src))
+ if(src:status_flags & GODMODE)
+ return
+ if(istype(src, /mob/living/carbon/human))
+ if(src:buckled)
+ return
+ if(src:shoes)
+ if(src:shoes.type == /obj/item/clothing/shoes/magboots)
+ if(src:shoes.flags & NOSLIP)
+ return
+ src << "\red You are pushed away by airflow!"
+ last_airflow = world.time
+ var/airflow_falloff = 9 - ul_FalloffAmount(airflow_dest) //It's a fast falloff calc. Very useful.
+ if(airflow_falloff < 1)
+ airflow_dest = null
+ return
+ airflow_speed = min(max(n * (9/airflow_falloff),1),9)
+ var
+ xo = -(airflow_dest.x - src.x)
+ yo = -(airflow_dest.y - src.y)
+ od = 0
+ airflow_dest = null
+ if(!density)
+ density = 1
+ od = 1
+ while(airflow_speed > 0)
+ if(airflow_speed <= 0) return
+ airflow_speed = min(airflow_speed,15)
+ airflow_speed -= vsc.airflow_speed_decay
+ if(airflow_speed > 7)
+ if(airflow_time++ >= airflow_speed - 7)
+ sleep(1 * tick_multiplier)
+ else
+ sleep(max(1,10-(airflow_speed+3)) * tick_multiplier)
+ if ((!( src.airflow_dest ) || src.loc == src.airflow_dest))
+ src.airflow_dest = locate(min(max(src.x + xo, 1), world.maxx), min(max(src.y + yo, 1), world.maxy), src.z)
+ if ((src.x == 1 || src.x == world.maxx || src.y == 1 || src.y == world.maxy))
+ return
+ if(!istype(loc, /turf))
+ return
+ step_towards(src, src.airflow_dest)
+ if(ismob(src) && src:client)
+ src:client:move_delay = world.time + vsc.airflow_mob_slowdown
+ airflow_dest = null
+ airflow_speed = 0
+ airflow_time = 0
+ if(od)
+ density = 0
+
+/atom/movable/Bump(atom/A)
+ if(airflow_speed > 0 && airflow_dest)
+ airflow_hit(A)
+ else
+ airflow_speed = 0
+ airflow_time = 0
+ . = ..()
atom/movable/proc/airflow_hit(atom/A)
airflow_speed = 0
diff --git a/code/ZAS/Connection.dm b/code/ZAS/Connection.dm
index f9697207c6..8a919d5043 100644
--- a/code/ZAS/Connection.dm
+++ b/code/ZAS/Connection.dm
@@ -6,393 +6,396 @@ Indirect connections will not merge the two zones after they reach equilibrium.
#define CONNECTION_INDIRECT 1
#define CONNECTION_CLOSED 0
+/connection
+ var/turf/simulated/A
+ var/turf/simulated/B
-connection
- var
- turf/simulated //The turfs involved in the connection.
- A
- B
- zone
- zone_A
- zone_B
- ref_A
- ref_B
- indirect = CONNECTION_DIRECT //If the connection is purely indirect, the zones should not join.
- last_updated //The tick at which this was last updated.
- no_zone_count = 0
+ var/zone/zone_A
+ var/zone/zone_B
+
+ var/ref_A
+ var/ref_B
+
+ var/indirect = CONNECTION_DIRECT //If the connection is purely indirect, the zones should not join.
+
+ var/last_updated //The tick at which this was last updated.
+
+ var/no_zone_count = 0
- New(turf/T,turf/O)
- A = T
- B = O
- if(A.zone && B.zone)
- if(!A.zone.connections) A.zone.connections = list()
- A.zone.connections += src
- zone_A = A.zone
- ref_A = "\ref[A]"
- if(!B.zone.connections) B.zone.connections = list()
- B.zone.connections += src
- zone_B = B.zone
- ref_B = "\ref[B]"
+/connection/New(turf/T,turf/O)
+ A = T
+ B = O
+ if(A.zone && B.zone)
+ if(!A.zone.connections) A.zone.connections = list()
+ A.zone.connections += src
+ zone_A = A.zone
+ ref_A = "\ref[A]"
- if(ref_A in air_master.turfs_with_connections)
- var/list/connections = air_master.turfs_with_connections[ref_A]
- connections.Add(src)
- else
- air_master.turfs_with_connections[ref_A] = list(src)
-
- if(ref_B in air_master.turfs_with_connections)
- var/list/connections = air_master.turfs_with_connections[ref_B]
- connections.Add(src)
- else
- air_master.turfs_with_connections[ref_B] = list(src)
-
- if(A.CanPass(null, B, 0, 0))
-
- ConnectZones(A.zone, B.zone, 1)
-
- if(A.HasDoor(B) || B.HasDoor(A))
- indirect = CONNECTION_INDIRECT
-
- else
- ConnectZones(A.zone, B.zone)
- indirect = CONNECTION_CLOSED
-
-
- else
- world.log << "Attempted to create connection object for non-zone tiles: [T] ([T.x],[T.y],[T.z]) -> [O] ([O.x],[O.y],[O.z])"
- del(src)
-
-
- Del()
- //remove connections from master lists.
- if(ref_B in air_master.turfs_with_connections)
- var/list/connections = air_master.turfs_with_connections[ref_B]
- connections.Remove(src)
+ if(!B.zone.connections) B.zone.connections = list()
+ B.zone.connections += src
+ zone_B = B.zone
+ ref_B = "\ref[B]"
if(ref_A in air_master.turfs_with_connections)
var/list/connections = air_master.turfs_with_connections[ref_A]
- connections.Remove(src)
+ connections.Add(src)
+ else
+ air_master.turfs_with_connections[ref_A] = list(src)
- //Remove connection from zones.
- if(A)
- if(A.zone && A.zone.connections)
- A.zone.connections.Remove(src)
- if(!A.zone.connections.len)
- A.zone.connections = null
+ if(ref_B in air_master.turfs_with_connections)
+ var/list/connections = air_master.turfs_with_connections[ref_B]
+ connections.Add(src)
+ else
+ air_master.turfs_with_connections[ref_B] = list(src)
- if(istype(zone_A) && (!A || A.zone != zone_A))
+ if(A.CanPass(null, B, 0, 0))
+
+ ConnectZones(A.zone, B.zone, 1)
+
+ if(A.HasDoor(B) || B.HasDoor(A))
+ indirect = CONNECTION_INDIRECT
+
+ else
+ ConnectZones(A.zone, B.zone)
+ indirect = CONNECTION_CLOSED
+
+
+ else
+ world.log << "Attempted to create connection object for non-zone tiles: [T] ([T.x],[T.y],[T.z]) -> [O] ([O.x],[O.y],[O.z])"
+ del(src)
+
+
+/connection/Del()
+ //remove connections from master lists.
+ if(ref_B in air_master.turfs_with_connections)
+ var/list/connections = air_master.turfs_with_connections[ref_B]
+ connections.Remove(src)
+
+ if(ref_A in air_master.turfs_with_connections)
+ var/list/connections = air_master.turfs_with_connections[ref_A]
+ connections.Remove(src)
+
+ //Remove connection from zones.
+ if(A)
+ if(A.zone && A.zone.connections)
+ A.zone.connections.Remove(src)
+ if(!A.zone.connections.len)
+ A.zone.connections = null
+
+ if(istype(zone_A) && (!A || A.zone != zone_A))
+ if(zone_A.connections)
+ zone_A.connections.Remove(src)
+ if(!zone_A.connections.len)
+ zone_A.connections = null
+
+ if(B)
+ if(B.zone && B.zone.connections)
+ B.zone.connections.Remove(src)
+ if(!B.zone.connections.len)
+ B.zone.connections = null
+
+ if(istype(zone_B) && (!B || B.zone != zone_B))
+ if(zone_B.connections)
+ zone_B.connections.Remove(src)
+ if(!zone_B.connections.len)
+ zone_B.connections = null
+
+ //Disconnect zones while handling unusual conditions.
+ // e.g. loss of a zone on a turf
+ if(A && A.zone && B && B.zone)
+ DisconnectZones(A.zone, B.zone)
+
+ //Finally, preform actual deletion.
+ . = ..()
+
+
+/connection/proc/ConnectZones(var/zone/zone_1, var/zone/zone_2, open = 0)
+
+ //Sanity checking
+ if(!istype(zone_1) || !istype(zone_2))
+ return
+
+ //Handle zones connecting indirectly/directly.
+ if(open)
+
+ //Create the lists if necessary.
+ if(!zone_1.connected_zones)
+ zone_1.connected_zones = list()
+
+ if(!zone_2.connected_zones)
+ zone_2.connected_zones = list()
+
+ //Increase the number of connections between zones.
+ if(zone_2 in zone_1.connected_zones)
+ zone_1.connected_zones[zone_2]++
+ else
+ zone_1.connected_zones += zone_2
+ zone_1.connected_zones[zone_2] = 1
+
+ if(zone_1 in zone_2.connected_zones)
+ zone_2.connected_zones[zone_1]++
+ else
+ zone_2.connected_zones += zone_1
+ zone_2.connected_zones[zone_1] = 1
+
+ //Handle closed connections.
+ else
+
+ //Create the lists
+ if(!zone_1.closed_connection_zones)
+ zone_1.closed_connection_zones = list()
+
+ if(!zone_2.closed_connection_zones)
+ zone_2.closed_connection_zones = list()
+
+ //Increment the connections.
+ if(zone_2 in zone_1.closed_connection_zones)
+ zone_1.closed_connection_zones[zone_2]++
+ else
+ zone_1.closed_connection_zones += zone_2
+ zone_1.closed_connection_zones[zone_2] = 1
+
+ if(zone_1 in zone_2.closed_connection_zones)
+ zone_2.closed_connection_zones[zone_1]++
+ else
+ zone_2.closed_connection_zones += zone_1
+ zone_2.closed_connection_zones[zone_1] = 1
+
+
+/connection/proc/DisconnectZones(var/zone/zone_1, var/zone/zone_2)
+ //Sanity checking
+ if(!istype(zone_1) || !istype(zone_2))
+ return
+
+ if(indirect != CONNECTION_CLOSED)
+ //Handle disconnection of indirectly or directly connected zones.
+ if( (zone_1 in zone_2.connected_zones) || (zone_2 in zone_1.connected_zones) )
+
+ //If there are more than one connection, decrement the number of connections
+ //Otherwise, remove all connections between the zones.
+ if(zone_2 in zone_1.connected_zones)
+ if(zone_1.connected_zones[zone_2] > 1)
+ zone_1.connected_zones[zone_2]--
+ else
+ zone_1.connected_zones -= zone_2
+ //remove the list if it is empty
+ if(!zone_1.connected_zones.len)
+ zone_1.connected_zones = null
+
+ //Then do the same for the other zone.
+ if(zone_1 in zone_2.connected_zones)
+ if(zone_2.connected_zones[zone_1] > 1)
+ zone_2.connected_zones[zone_1]--
+ else
+ zone_2.connected_zones -= zone_1
+ if(!zone_2.connected_zones.len)
+ zone_2.connected_zones = null
+
+ else
+ //Handle disconnection of closed zones.
+ if( (zone_1 in zone_2.closed_connection_zones) || (zone_2 in zone_1.closed_connection_zones) )
+
+ //If there are more than one connection, decrement the number of connections
+ //Otherwise, remove all connections between the zones.
+ if(zone_2 in zone_1.closed_connection_zones)
+ if(zone_1.closed_connection_zones[zone_2] > 1)
+ zone_1.closed_connection_zones[zone_2]--
+ else
+ zone_1.closed_connection_zones -= zone_2
+ //remove the list if it is empty
+ if(!zone_1.closed_connection_zones.len)
+ zone_1.closed_connection_zones = null
+
+ //Then do the same for the other zone.
+ if(zone_1 in zone_2.closed_connection_zones)
+ if(zone_2.closed_connection_zones[zone_1] > 1)
+ zone_2.closed_connection_zones[zone_1]--
+ else
+ zone_2.closed_connection_zones -= zone_1
+ if(!zone_2.closed_connection_zones.len)
+ zone_2.closed_connection_zones = null
+
+
+/connection/proc/Cleanup()
+
+ //Check sanity: existance of turfs
+ if(!A || !B)
+ del src
+
+ //Check sanity: zones are different
+ if(A.zone == B.zone)
+ del src
+
+ //Check sanity: same turfs as before.
+ if(ref_A != "\ref[A]" || ref_B != "\ref[B]")
+ del src
+
+ //Handle zones changing on a turf.
+ if((A.zone && A.zone != zone_A) || (B.zone && B.zone != zone_B))
+ Sanitize()
+
+ //Manage sudden loss of a turfs zone. (e.g. a wall being built)
+ if(!A.zone || !B.zone)
+ no_zone_count++
+ if(no_zone_count >= 5)
+ //world.log << "Connection removed: [A] or [B] missing a zone."
+ del src
+ return 0
+
+ return 1
+
+
+/connection/proc/CheckPassSanity()
+ //Sanity check, first.
+ Cleanup()
+
+ if(A.zone && B.zone)
+
+ //If no walls are blocking us...
+ if(A.ZAirPass(B))
+ //...we check to see if there is a door in the way...
+ var/door_pass = A.CanPass(null,B,1.5,1)
+ //...and if it is opened.
+ if(door_pass || A.CanPass(null,B,0,0))
+
+ //Make and remove connections to let air pass.
+ if(indirect == CONNECTION_CLOSED)
+ DisconnectZones(A.zone, B.zone)
+ ConnectZones(A.zone, B.zone, 1)
+
+ if(door_pass)
+ indirect = CONNECTION_DIRECT
+ else if(!door_pass)
+ indirect = CONNECTION_INDIRECT
+
+ //The door is instead closed.
+ else if(indirect > CONNECTION_CLOSED)
+ DisconnectZones(A.zone, B.zone)
+ indirect = CONNECTION_CLOSED
+ ConnectZones(A.zone, B.zone)
+
+ //If I can no longer pass air, better delete
+ else
+ del src
+
+/connection/proc/Sanitize()
+ //If the zones change on connected turfs, update it.
+
+ //Both zones changed (wat)
+ if(A.zone && A.zone != zone_A && B.zone && B.zone != zone_B)
+
+ //If the zones have gotten swapped
+ // (do not ask me how, I am just being anal retentive about sanity)
+ if(A.zone == zone_B && B.zone == zone_A)
+ var/turf/temp = B
+ B = A
+ A = temp
+ zone_B = B.zone
+ zone_A = A.zone
+ var/temp_ref = ref_A
+ ref_A = ref_B
+ ref_B = temp_ref
+ return
+
+ //Handle removal of connections from archived zones.
+ if(zone_A && zone_A.connections)
+ zone_A.connections.Remove(src)
+ if(!zone_A.connections.len)
+ zone_A.connections = null
+
+ if(zone_B && zone_B.connections)
+ zone_B.connections.Remove(src)
+ if(!zone_B.connections.len)
+ zone_B.connections = null
+
+ if(A.zone)
+ if(!A.zone.connections)
+ A.zone.connections = list()
+ A.zone.connections |= src
+
+ if(B.zone)
+ if(!B.zone.connections)
+ B.zone.connections = list()
+ B.zone.connections |= src
+
+ //If either zone is null, we disconnect the archived ones after cleaning up the connections.
+ if(!A.zone || !B.zone)
+ if(zone_A && zone_B)
+ DisconnectZones(zone_B, zone_A)
+
+ if(!A.zone)
+ zone_A = A.zone
+
+ if(!B.zone)
+ zone_B = B.zone
+ return
+
+ //Handle diconnection and reconnection of zones.
+ if(zone_A && zone_B)
+ DisconnectZones(zone_A, zone_B)
+ ConnectZones(A.zone, B.zone, indirect)
+
+ //resetting values of archived values.
+ zone_B = B.zone
+ zone_A = A.zone
+
+ //The "A" zone changed.
+ else if(A.zone && A.zone != zone_A)
+
+ //Handle connection cleanup
+ if(zone_A)
if(zone_A.connections)
zone_A.connections.Remove(src)
if(!zone_A.connections.len)
zone_A.connections = null
- if(B)
- if(B.zone && B.zone.connections)
- B.zone.connections.Remove(src)
- if(!B.zone.connections.len)
- B.zone.connections = null
+ if(A.zone)
+ if(!A.zone.connections)
+ A.zone.connections = list()
+ A.zone.connections |= src
- if(istype(zone_B) && (!B || B.zone != zone_B))
+ //If the "A" zone is null, we disconnect the archived ones after cleaning up the connections.
+ if(!A.zone)
+ if(zone_A && zone_B)
+ DisconnectZones(zone_A, zone_B)
+ zone_A = A.zone
+ return
+
+ //Handle diconnection and reconnection of zones.
+ if(zone_A && zone_B)
+ DisconnectZones(zone_A, zone_B)
+ ConnectZones(A.zone, B.zone, indirect)
+ zone_A = A.zone
+
+ //The "B" zone changed.
+ else if(B.zone && B.zone != zone_B)
+
+ //Handle connection cleanup
+ if(zone_B)
if(zone_B.connections)
zone_B.connections.Remove(src)
if(!zone_B.connections.len)
zone_B.connections = null
- //Disconnect zones while handling unusual conditions.
- // e.g. loss of a zone on a turf
- if(A && A.zone && B && B.zone)
- DisconnectZones(A.zone, B.zone)
+ if(B.zone)
+ if(!B.zone.connections)
+ B.zone.connections = list()
+ B.zone.connections |= src
- //Finally, preform actual deletion.
- . = ..()
-
-
- proc/ConnectZones(var/zone/zone_1, var/zone/zone_2, open = 0)
-
- //Sanity checking
- if(!istype(zone_1) || !istype(zone_2))
- return
-
- //Handle zones connecting indirectly/directly.
- if(open)
-
- //Create the lists if necessary.
- if(!zone_1.connected_zones)
- zone_1.connected_zones = list()
-
- if(!zone_2.connected_zones)
- zone_2.connected_zones = list()
-
- //Increase the number of connections between zones.
- if(zone_2 in zone_1.connected_zones)
- zone_1.connected_zones[zone_2]++
- else
- zone_1.connected_zones += zone_2
- zone_1.connected_zones[zone_2] = 1
-
- if(zone_1 in zone_2.connected_zones)
- zone_2.connected_zones[zone_1]++
- else
- zone_2.connected_zones += zone_1
- zone_2.connected_zones[zone_1] = 1
-
- //Handle closed connections.
- else
-
- //Create the lists
- if(!zone_1.closed_connection_zones)
- zone_1.closed_connection_zones = list()
-
- if(!zone_2.closed_connection_zones)
- zone_2.closed_connection_zones = list()
-
- //Increment the connections.
- if(zone_2 in zone_1.closed_connection_zones)
- zone_1.closed_connection_zones[zone_2]++
- else
- zone_1.closed_connection_zones += zone_2
- zone_1.closed_connection_zones[zone_2] = 1
-
- if(zone_1 in zone_2.closed_connection_zones)
- zone_2.closed_connection_zones[zone_1]++
- else
- zone_2.closed_connection_zones += zone_1
- zone_2.closed_connection_zones[zone_1] = 1
-
-
- proc/DisconnectZones(var/zone/zone_1, var/zone/zone_2)
-
- //Sanity checking
- if(!istype(zone_1) || !istype(zone_2))
- return
-
- if(indirect != CONNECTION_CLOSED)
- //Handle disconnection of indirectly or directly connected zones.
- if( (zone_1 in zone_2.connected_zones) || (zone_2 in zone_1.connected_zones) )
-
- //If there are more than one connection, decrement the number of connections
- //Otherwise, remove all connections between the zones.
- if(zone_2 in zone_1.connected_zones)
- if(zone_1.connected_zones[zone_2] > 1)
- zone_1.connected_zones[zone_2]--
- else
- zone_1.connected_zones -= zone_2
- //remove the list if it is empty
- if(!zone_1.connected_zones.len)
- zone_1.connected_zones = null
-
- //Then do the same for the other zone.
- if(zone_1 in zone_2.connected_zones)
- if(zone_2.connected_zones[zone_1] > 1)
- zone_2.connected_zones[zone_1]--
- else
- zone_2.connected_zones -= zone_1
- if(!zone_2.connected_zones.len)
- zone_2.connected_zones = null
-
- else
- //Handle disconnection of closed zones.
- if( (zone_1 in zone_2.closed_connection_zones) || (zone_2 in zone_1.closed_connection_zones) )
-
- //If there are more than one connection, decrement the number of connections
- //Otherwise, remove all connections between the zones.
- if(zone_2 in zone_1.closed_connection_zones)
- if(zone_1.closed_connection_zones[zone_2] > 1)
- zone_1.closed_connection_zones[zone_2]--
- else
- zone_1.closed_connection_zones -= zone_2
- //remove the list if it is empty
- if(!zone_1.closed_connection_zones.len)
- zone_1.closed_connection_zones = null
-
- //Then do the same for the other zone.
- if(zone_1 in zone_2.closed_connection_zones)
- if(zone_2.closed_connection_zones[zone_1] > 1)
- zone_2.closed_connection_zones[zone_1]--
- else
- zone_2.closed_connection_zones -= zone_1
- if(!zone_2.closed_connection_zones.len)
- zone_2.closed_connection_zones = null
-
-
- proc/Cleanup()
-
- //Check sanity: existance of turfs
- if(!A || !B)
- del src
-
- //Check sanity: zones are different
- if(A.zone == B.zone)
- del src
-
- //Check sanity: same turfs as before.
- if(ref_A != "\ref[A]" || ref_B != "\ref[B]")
- del src
-
- //Handle zones changing on a turf.
- if((A.zone && A.zone != zone_A) || (B.zone && B.zone != zone_B))
- Sanitize()
-
- //Manage sudden loss of a turfs zone. (e.g. a wall being built)
- if(!A.zone || !B.zone)
- no_zone_count++
- if(no_zone_count >= 5)
- //world.log << "Connection removed: [A] or [B] missing a zone."
- del src
- return 0
-
- return 1
-
-
- proc/CheckPassSanity()
- //Sanity check, first.
- Cleanup()
-
- if(A.zone && B.zone)
-
- //If no walls are blocking us...
- if(A.ZAirPass(B))
- //...we check to see if there is a door in the way...
- var/door_pass = A.CanPass(null,B,1.5,1)
- //...and if it is opened.
- if(door_pass || A.CanPass(null,B,0,0))
-
- //Make and remove connections to let air pass.
- if(indirect == CONNECTION_CLOSED)
- DisconnectZones(A.zone, B.zone)
- ConnectZones(A.zone, B.zone, 1)
-
- if(door_pass)
- indirect = CONNECTION_DIRECT
- else if(!door_pass)
- indirect = CONNECTION_INDIRECT
-
- //The door is instead closed.
- else if(indirect > CONNECTION_CLOSED)
- DisconnectZones(A.zone, B.zone)
- indirect = CONNECTION_CLOSED
- ConnectZones(A.zone, B.zone)
-
- //If I can no longer pass air, better delete
- else
- del src
-
- proc/Sanitize()
- //If the zones change on connected turfs, update it.
-
- //Both zones changed (wat)
- if(A.zone && A.zone != zone_A && B.zone && B.zone != zone_B)
-
- //If the zones have gotten swapped
- // (do not ask me how, I am just being anal retentive about sanity)
- if(A.zone == zone_B && B.zone == zone_A)
- var/turf/temp = B
- B = A
- A = temp
- zone_B = B.zone
- zone_A = A.zone
- var/temp_ref = ref_A
- ref_A = ref_B
- ref_B = temp_ref
- return
-
- //Handle removal of connections from archived zones.
- if(zone_A && zone_A.connections)
- zone_A.connections.Remove(src)
- if(!zone_A.connections.len)
- zone_A.connections = null
-
- if(zone_B && zone_B.connections)
- zone_B.connections.Remove(src)
- if(!zone_B.connections.len)
- zone_B.connections = null
-
- if(A.zone)
- if(!A.zone.connections)
- A.zone.connections = list()
- A.zone.connections |= src
-
- if(B.zone)
- if(!B.zone.connections)
- B.zone.connections = list()
- B.zone.connections |= src
-
- //If either zone is null, we disconnect the archived ones after cleaning up the connections.
- if(!A.zone || !B.zone)
- if(zone_A && zone_B)
- DisconnectZones(zone_B, zone_A)
-
- if(!A.zone)
- zone_A = A.zone
-
- if(!B.zone)
- zone_B = B.zone
- return
-
- //Handle diconnection and reconnection of zones.
+ //If the "B" zone is null, we disconnect the archived ones after cleaning up the connections.
+ if(!B.zone)
if(zone_A && zone_B)
DisconnectZones(zone_A, zone_B)
- ConnectZones(A.zone, B.zone, indirect)
-
- //resetting values of archived values.
zone_B = B.zone
- zone_A = A.zone
+ return
- //The "A" zone changed.
- else if(A.zone && A.zone != zone_A)
-
- //Handle connection cleanup
- if(zone_A)
- if(zone_A.connections)
- zone_A.connections.Remove(src)
- if(!zone_A.connections.len)
- zone_A.connections = null
-
- if(A.zone)
- if(!A.zone.connections)
- A.zone.connections = list()
- A.zone.connections |= src
-
- //If the "A" zone is null, we disconnect the archived ones after cleaning up the connections.
- if(!A.zone)
- if(zone_A && zone_B)
- DisconnectZones(zone_A, zone_B)
- zone_A = A.zone
- return
-
- //Handle diconnection and reconnection of zones.
- if(zone_A && zone_B)
- DisconnectZones(zone_A, zone_B)
- ConnectZones(A.zone, B.zone, indirect)
-
- //The "B" zone changed.
- else if(B.zone && B.zone != zone_B)
-
- //Handle connection cleanup
- if(zone_B)
- if(zone_B.connections)
- zone_B.connections.Remove(src)
- if(!zone_B.connections.len)
- zone_B.connections = null
-
- if(B.zone)
- if(!B.zone.connections)
- B.zone.connections = list()
- B.zone.connections |= src
-
- //If the "B" zone is null, we disconnect the archived ones after cleaning up the connections.
- if(!B.zone)
- if(zone_A && zone_B)
- DisconnectZones(zone_A, zone_B)
- zone_B = B.zone
- return
-
- //Handle diconnection and reconnection of zones.
- if(zone_A && zone_B)
- DisconnectZones(zone_A, zone_B)
- ConnectZones(A.zone, B.zone, indirect)
+ //Handle diconnection and reconnection of zones.
+ if(zone_A && zone_B)
+ DisconnectZones(zone_A, zone_B)
+ ConnectZones(A.zone, B.zone, indirect)
+ zone_B = B.zone
#undef CONNECTION_DIRECT
diff --git a/code/ZAS/Debug.dm b/code/ZAS/Debug.dm
index b3f069a554..807208a5a3 100644
--- a/code/ZAS/Debug.dm
+++ b/code/ZAS/Debug.dm
@@ -8,7 +8,8 @@ client/proc/Zone_Info(turf/T as null|turf)
mob << "No zone here."
else
if(zone_debug_images)
- images -= zone_debug_images
+ for(var/zone in zone_debug_images)
+ images -= zone_debug_images[zone]
zone_debug_images = null
client/var/list/zone_debug_images
@@ -23,12 +24,12 @@ client/proc/Test_ZAS_Connection(var/turf/simulated/T as turf)
"South" = SOUTH,\
"East" = EAST,\
"West" = WEST,\
- "None" = null)
+ "N/A" = null)
var/direction = input("What direction do you wish to test?","Set direction") as null|anything in direction_list
if(!direction)
return
- if(direction == "None")
+ if(direction == "N/A")
if(T.CanPass(null, T, 0,0))
mob << "The turf can pass air! :D"
else
@@ -55,61 +56,67 @@ client/proc/Test_ZAS_Connection(var/turf/simulated/T as turf)
mob << "Both turfs can connect! :)"
-zone/proc
- DebugDisplay(client/client)
- if(!istype(client))
- return
+zone/proc/DebugDisplay(client/client)
+ if(!istype(client))
+ return
- if(!dbg_output)
- dbg_output = 1 //Don't want to be spammed when someone investigates a zone...
+ if(!dbg_output)
+ dbg_output = 1 //Don't want to be spammed when someone investigates a zone...
- if(!client.zone_debug_images)
- client.zone_debug_images = list()
- for(var/turf/T in contents)
- client.zone_debug_images += image('debug_group.dmi', T)
+ if(!client.zone_debug_images)
+ client.zone_debug_images = list()
- for(var/turf/space/S in unsimulated_tiles)
- client.zone_debug_images += image('debug_space.dmi', S)
+ var/list/current_zone_images = list()
- client << "Zone Air Contents"
- client << "Oxygen: [air.oxygen]"
- client << "Nitrogen: [air.nitrogen]"
- client << "Plasma: [air.toxins]"
- client << "Carbon Dioxide: [air.carbon_dioxide]"
- client << "Temperature: [air.temperature] K"
- client << "Heat Energy: [air.temperature * air.heat_capacity()] J"
- client << "Pressure: [air.return_pressure()] KPa"
- client << ""
- client << "Space Tiles: [length(unsimulated_tiles)]"
- client << "Movable Objects: [length(movables())]"
- client << "Connections: [length(connections)]"
+ for(var/turf/T in contents)
+ current_zone_images += image('debug_group.dmi', T, null, TURF_LAYER)
- for(var/connection/C in connections)
- client << "\ref[C] [C.A] --> [C.B] [(C.indirect?"Open":"Closed")]"
- client.zone_debug_images += image('debug_connect.dmi', C.A)
- client.zone_debug_images += image('debug_connect.dmi', C.B)
+ for(var/turf/space/S in unsimulated_tiles)
+ current_zone_images += image('debug_space.dmi', S, null, TURF_LAYER)
- client << "Connected Zones:"
- for(var/zone/zone in connected_zones)
- client << "\ref[zone] [zone] - [connected_zones[zone]] (Connected)"
+ client << "Zone Air Contents"
+ client << "Oxygen: [air.oxygen]"
+ client << "Nitrogen: [air.nitrogen]"
+ client << "Plasma: [air.toxins]"
+ client << "Carbon Dioxide: [air.carbon_dioxide]"
+ client << "Temperature: [air.temperature] K"
+ client << "Heat Energy: [air.temperature * air.heat_capacity()] J"
+ client << "Pressure: [air.return_pressure()] KPa"
+ client << ""
+ client << "Space Tiles: [length(unsimulated_tiles)]"
+ client << "Movable Objects: [length(movables())]"
+ client << "Connections: [length(connections)]"
- for(var/zone/zone in closed_connection_zones)
- client << "\ref[zone] [zone] - [closed_connection_zones[zone]] (Unconnected)"
+ for(var/connection/C in connections)
+ client << "\ref[C] [C.A] --> [C.B] [(C.indirect?"Open":"Closed")]"
+ current_zone_images += image('debug_connect.dmi', C.A, null, TURF_LAYER)
+ current_zone_images += image('debug_connect.dmi', C.B, null, TURF_LAYER)
- for(var/C in connections)
- if(!istype(C,/connection))
- client << "[C] (Not Connection!)"
+ client << "Connected Zones:"
+ for(var/zone/zone in connected_zones)
+ client << "\ref[zone] [zone] - [connected_zones[zone]] (Connected)"
- client.images += client.zone_debug_images
+ for(var/zone/zone in closed_connection_zones)
+ client << "\ref[zone] [zone] - [closed_connection_zones[zone]] (Unconnected)"
- else
- dbg_output = 0
+ for(var/C in connections)
+ if(!istype(C,/connection))
+ client << "[C] (Not Connection!)"
- client.images -= client.zone_debug_images
- client.zone_debug_images = null
+ if(!client.zone_debug_images)
+ client.zone_debug_images = list()
+ client.zone_debug_images[src] = current_zone_images
- for(var/zone/Z in zones)
- if(Z.air == air && Z != src)
- var/turf/zloc = pick(Z.contents)
- client << "\red Illegal air datum shared by: [zloc.loc.name]"
+ client.images += client.zone_debug_images[src]
+
+ else
+ dbg_output = 0
+
+ client.images -= client.zone_debug_images[src]
+ client.zone_debug_images.Remove(src)
+
+ for(var/zone/Z in zones)
+ if(Z.air == air && Z != src)
+ var/turf/zloc = pick(Z.contents)
+ client << "\red Illegal air datum shared by: [zloc.loc.name]"
diff --git a/code/ZAS/FEA_gas_mixture.dm b/code/ZAS/FEA_gas_mixture.dm
index a4104ab01c..8b7ab992c9 100644
--- a/code/ZAS/FEA_gas_mixture.dm
+++ b/code/ZAS/FEA_gas_mixture.dm
@@ -14,141 +14,135 @@ What are the archived variables for?
#define QUANTIZE(variable) (round(variable,0.0001))
#define TRANSFER_FRACTION 5 //What fraction (1/#) of the air difference to try and transfer
-datum
- gas //These are used for the "Trace Gases" stuff, but is buggy.
- sleeping_agent
- specific_heat = 40
+/datum/gas/sleeping_agent/specific_heat = 40 //These are used for the "Trace Gases" stuff, but is buggy.
- oxygen_agent_b
- specific_heat = 300
+/datum/gas/oxygen_agent_b/specific_heat = 300
- volatile_fuel
- specific_heat = 30
+/datum/gas/volatile_fuel/specific_heat = 30
- var
- moles = 0
- specific_heat = 0
+/datum/gas
+ var/moles = 0
- moles_archived = 0
+ var/specific_heat = 0
- gas_mixture
- var //Holds the "moles" of each of the four gases.
- oxygen = 0
- carbon_dioxide = 0
- nitrogen = 0
- toxins = 0
- total_moles = 0 //Updated when a reaction occurs.
+ var/moles_archived = 0
- volume = CELL_VOLUME
+/datum/gas_mixture/
+ var/oxygen = 0 //Holds the "moles" of each of the four gases.
+ var/carbon_dioxide = 0
+ var/nitrogen = 0
+ var/toxins = 0
- temperature = 0 //in Kelvin, use calculate_temperature() to modify
+ var/total_moles = 0 //Updated when a reaction occurs.
- group_multiplier = 1
+ var/volume = CELL_VOLUME
+
+ var/temperature = 0 //in Kelvin, use calculate_temperature() to modify
+
+ var/group_multiplier = 1
//Size of the group this gas_mixture is representing.
//=1 for singletons
- graphic
+ var/graphic
- list/datum/gas/trace_gases = list() //Seemed to be a good idea that was abandoned
+ var/list/datum/gas/trace_gases = list() //Seemed to be a good idea that was abandoned
- tmp //These are variables for use with the archived data
- oxygen_archived
- carbon_dioxide_archived
- nitrogen_archived
- toxins_archived
+ var/tmp/oxygen_archived //These are variables for use with the archived data
+ var/tmp/carbon_dioxide_archived
+ var/tmp/nitrogen_archived
+ var/tmp/toxins_archived
- temperature_archived
+ var/tmp/temperature_archived
- graphic_archived = 0
- fuel_burnt = 0
+ var/tmp/graphic_archived = 0
+ var/tmp/fuel_burnt = 0
//FOR THE LOVE OF GOD PLEASE USE THIS PROC
//Call it with negative numbers to remove gases.
- proc/adjust(o2 = 0, co2 = 0, n2 = 0, tx = 0, list/datum/gas/traces = list())
- //Purpose: Adjusting the gases within a airmix
- //Called by: Nothing, yet!
- //Inputs: The values of the gases to adjust
- //Outputs: null
+/datum/gas_mixture/proc/adjust(o2 = 0, co2 = 0, n2 = 0, tx = 0, list/datum/gas/traces = list())
+ //Purpose: Adjusting the gases within a airmix
+ //Called by: Nothing, yet!
+ //Inputs: The values of the gases to adjust
+ //Outputs: null
- oxygen = max(0, oxygen + o2)
- carbon_dioxide = max(0, carbon_dioxide + co2)
- nitrogen = max(0, nitrogen + n2)
- toxins = max(0, toxins + tx)
+ 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
+ //handle trace gasses
+ for(var/datum/gas/G in traces)
+ var/datum/gas/T = locate(G.type) in trace_gases
+ if(T)
+ T.moles = max(G.moles + T.moles, 0)
+ else if(G.moles > 0)
+ trace_gases |= G
+ update_values()
+ return
//tg seems to like using these a lot
- proc/return_temperature()
- return temperature
+/datum/gas_mixture/proc/return_temperature()
+ return temperature
- proc/return_volume()
- return max(0, volume)
+/datum/gas_mixture/proc/return_volume()
+ return max(0, volume)
- proc/thermal_energy()
- return temperature*heat_capacity()
+/datum/gas_mixture/proc/thermal_energy()
+ return temperature*heat_capacity()
///////////////////////////////
//PV=nRT - related procedures//
///////////////////////////////
+/datum/gas_mixture/proc/heat_capacity()
+ //Purpose: Returning the heat capacity of the gas mix
+ //Called by: UNKNOWN
+ //Inputs: None
+ //Outputs: Heat capacity
- proc/heat_capacity()
- //Purpose: Returning the heat capacity of the gas mix
- //Called by: UNKNOWN
- //Inputs: None
- //Outputs: Heat capacity
+ var/heat_capacity = HEAT_CAPACITY_CALCULATION(oxygen,carbon_dioxide,nitrogen,toxins)
- 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
- if(trace_gases.len)
- for(var/datum/gas/trace_gas in trace_gases)
- heat_capacity += trace_gas.moles*trace_gas.specific_heat
+ return max(MINIMUM_HEAT_CAPACITY,heat_capacity)
- return max(MINIMUM_HEAT_CAPACITY,heat_capacity)
+/datum/gas_mixture/proc/heat_capacity_archived()
+ //Purpose: Returning the archived heat capacity of the gas mix
+ //Called by: UNKNOWN
+ //Inputs: None
+ //Outputs: Archived heat capacity
- proc/heat_capacity_archived()
- //Purpose: Returning the archived heat capacity of the gas mix
- //Called by: UNKNOWN
- //Inputs: None
- //Outputs: Archived heat capacity
+ var/heat_capacity_archived = HEAT_CAPACITY_CALCULATION(oxygen_archived,carbon_dioxide_archived,nitrogen_archived,toxins_archived)
- var/heat_capacity_archived = HEAT_CAPACITY_CALCULATION(oxygen_archived,carbon_dioxide_archived,nitrogen_archived,toxins_archived)
+ if(trace_gases.len)
+ for(var/datum/gas/trace_gas in trace_gases)
+ heat_capacity_archived += trace_gas.moles_archived*trace_gas.specific_heat
- if(trace_gases.len)
- for(var/datum/gas/trace_gas in trace_gases)
- heat_capacity_archived += trace_gas.moles_archived*trace_gas.specific_heat
+ return max(MINIMUM_HEAT_CAPACITY,heat_capacity_archived)
- return max(MINIMUM_HEAT_CAPACITY,heat_capacity_archived)
+/datum/gas_mixture/proc/total_moles()
+ return total_moles
+ /*var/moles = oxygen + carbon_dioxide + nitrogen + toxins
- proc/total_moles()
- return total_moles
- /*var/moles = oxygen + carbon_dioxide + nitrogen + toxins
+ if(trace_gases.len)
+ for(var/datum/gas/trace_gas in trace_gases)
+ moles += trace_gas.moles
+ return moles*/
- if(trace_gases.len)
- for(var/datum/gas/trace_gas in trace_gases)
- moles += trace_gas.moles
- return moles*/
+/datum/gas_mixture/proc/return_pressure()
+ //Purpose: Calculating Current Pressure
+ //Called by:
+ //Inputs: None
+ //Outputs: Gas pressure.
- proc/return_pressure()
- //Purpose: Calculating Current Pressure
- //Called by:
- //Inputs: None
- //Outputs: Gas pressure.
-
- if(volume>0)
- return total_moles()*R_IDEAL_GAS_EQUATION*temperature/volume
- return 0
+ if(volume>0)
+ return total_moles()*R_IDEAL_GAS_EQUATION*temperature/volume
+ return 0
// proc/return_temperature()
//Purpose:
@@ -171,868 +165,865 @@ datum
// 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
+/datum/gas_mixture/proc/update_values()
+ //Purpose: Calculating and storing values which were normally called CONSTANTLY
+ //Called by: Anything that changes values within a gas mix.
+ //Inputs: None
+ //Outputs: None
- total_moles = oxygen + carbon_dioxide + nitrogen + toxins
+ 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
+ if(trace_gases.len)
+ for(var/datum/gas/trace_gas in trace_gases)
+ total_moles += trace_gas.moles
- return
+ return
////////////////////////////////////////////
//Procedures used for very specific events//
////////////////////////////////////////////
+/datum/gas_mixture/proc/check_tile_graphic()
+ //Purpose: Calculating the graphic for a tile
+ //Called by: Turfs updating
+ //Inputs: None
+ //Outputs: 1 if graphic changed, 0 if unchanged
- proc/check_tile_graphic()
- //Purpose: Calculating the graphic for a tile
- //Called by: Turfs updating
- //Inputs: None
- //Outputs: 1 if graphic changed, 0 if unchanged
-
+ graphic = 0
+ if(toxins > MOLES_PLASMA_VISIBLE)
+ graphic = 1
+ else if(length(trace_gases))
+ var/datum/gas/sleeping_agent = locate(/datum/gas/sleeping_agent) in trace_gases
+ if(sleeping_agent && (sleeping_agent.moles > 1))
+ graphic = 2
+ else
graphic = 0
- if(toxins > MOLES_PLASMA_VISIBLE)
- graphic = 1
- else if(length(trace_gases))
- var/datum/gas/sleeping_agent = locate(/datum/gas/sleeping_agent) in trace_gases
- if(sleeping_agent && (sleeping_agent.moles > 1))
- graphic = 2
- else
- graphic = 0
- return graphic != graphic_archived
+ 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
+/datum/gas_mixture/proc/react(atom/dump_location)
+ //Purpose: Calculating if it is possible for a fire to occur in the airmix
+ //Called by: Air mixes updating?
+ //Inputs: None
+ //Outputs: If a fire occured
- var/reacting = 0 //set to 1 if a notable reaction occured (used by pipe_network)
+ var/reacting = 0 //set to 1 if a notable reaction occured (used by pipe_network)
- if(temperature > FIRE_MINIMUM_TEMPERATURE_TO_EXIST)
- if(zburn(null) > 0)
- reacting = 1
+ if(temperature > FIRE_MINIMUM_TEMPERATURE_TO_EXIST)
+ if(zburn(null) > 0)
+ reacting = 1
- return reacting
+ return reacting
- proc/fire()
- //Purpose: Calculating any fire reactions.
- //Called by: react() (See above)
- //Inputs: None
- //Outputs: How much fuel burned
+/datum/gas_mixture/proc/fire()
+ //Purpose: Calculating any fire reactions.
+ //Called by: react() (See above)
+ //Inputs: None
+ //Outputs: How much fuel burned
- return zburn(null)
+ return zburn(null)
- /*var/energy_released = 0
- var/old_heat_capacity = heat_capacity()
+ /*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
+ 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)
+ 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
+ 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
+ //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)
+ energy_released += FIRE_PLASMA_ENERGY_RELEASED * (plasma_burn_rate)
- fuel_burnt += (plasma_burn_rate)*(1+oxygen_burn_rate)
+ fuel_burnt += (plasma_burn_rate)*(1+oxygen_burn_rate)
- if(energy_released > 0)
- var/new_heat_capacity = heat_capacity()
- if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
- temperature = (temperature*old_heat_capacity + energy_released)/new_heat_capacity
- update_values()
+ if(energy_released > 0)
+ var/new_heat_capacity = heat_capacity()
+ if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
+ temperature = (temperature*old_heat_capacity + energy_released)/new_heat_capacity
+ update_values()
- return fuel_burnt*/
+ return fuel_burnt*/
//////////////////////////////////////////////
//Procs for general gas spread calculations.//
//////////////////////////////////////////////
- proc/archive()
- //Purpose: Archives the current gas values
- //Called by: UNKNOWN
- //Inputs: None
- //Outputs: 1
+/datum/gas_mixture/proc/archive()
+ //Purpose: Archives the current gas values
+ //Called by: UNKNOWN
+ //Inputs: None
+ //Outputs: 1
- oxygen_archived = oxygen
- carbon_dioxide_archived = carbon_dioxide
- nitrogen_archived = nitrogen
- toxins_archived = toxins
+ oxygen_archived = oxygen
+ carbon_dioxide_archived = carbon_dioxide
+ nitrogen_archived = nitrogen
+ toxins_archived = toxins
- if(trace_gases.len)
- for(var/datum/gas/trace_gas in trace_gases)
- trace_gas.moles_archived = trace_gas.moles
+ if(trace_gases.len)
+ for(var/datum/gas/trace_gas in trace_gases)
+ trace_gas.moles_archived = trace_gas.moles
- temperature_archived = temperature
+ temperature_archived = temperature
- graphic_archived = graphic
+ graphic_archived = graphic
- return 1
+ return 1
- proc/check_then_merge(datum/gas_mixture/giver)
- //Purpose: Similar to merge(...) but first checks to see if the amount of air assumed is small enough
- // that group processing is still accurate for source (aborts if not)
- //Called by: airgroups/machinery expelling air, ?
- //Inputs: The gas to try and merge
- //Outputs: 1 on successful merge. 0 otherwise.
+/datum/gas_mixture/proc/check_then_merge(datum/gas_mixture/giver)
+ //Purpose: Similar to merge(...) but first checks to see if the amount of air assumed is small enough
+ // that group processing is still accurate for source (aborts if not)
+ //Called by: airgroups/machinery expelling air, ?
+ //Inputs: The gas to try and merge
+ //Outputs: 1 on successful merge. 0 otherwise.
- if(!giver)
- return 0
- if(((giver.oxygen > MINIMUM_AIR_TO_SUSPEND) && (giver.oxygen >= oxygen*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
- || ((giver.carbon_dioxide > MINIMUM_AIR_TO_SUSPEND) && (giver.carbon_dioxide >= carbon_dioxide*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
- || ((giver.nitrogen > MINIMUM_AIR_TO_SUSPEND) && (giver.nitrogen >= nitrogen*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
- || ((giver.toxins > MINIMUM_AIR_TO_SUSPEND) && (giver.toxins >= toxins*MINIMUM_AIR_RATIO_TO_SUSPEND)))
- return 0
- if(abs(giver.temperature - temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND)
+ if(!giver)
+ return 0
+ if(((giver.oxygen > MINIMUM_AIR_TO_SUSPEND) && (giver.oxygen >= oxygen*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
+ || ((giver.carbon_dioxide > MINIMUM_AIR_TO_SUSPEND) && (giver.carbon_dioxide >= carbon_dioxide*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
+ || ((giver.nitrogen > MINIMUM_AIR_TO_SUSPEND) && (giver.nitrogen >= nitrogen*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
+ || ((giver.toxins > MINIMUM_AIR_TO_SUSPEND) && (giver.toxins >= toxins*MINIMUM_AIR_RATIO_TO_SUSPEND)))
+ return 0
+ if(abs(giver.temperature - temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND)
+ return 0
+
+ if(giver.trace_gases.len)
+ for(var/datum/gas/trace_gas in giver.trace_gases)
+ var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases
+ if((trace_gas.moles > MINIMUM_AIR_TO_SUSPEND) && (!corresponding || (trace_gas.moles >= corresponding.moles*MINIMUM_AIR_RATIO_TO_SUSPEND)))
return 0
- if(giver.trace_gases.len)
- for(var/datum/gas/trace_gas in giver.trace_gases)
- var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases
- if((trace_gas.moles > MINIMUM_AIR_TO_SUSPEND) && (!corresponding || (trace_gas.moles >= corresponding.moles*MINIMUM_AIR_RATIO_TO_SUSPEND)))
+ return merge(giver)
+
+/datum/gas_mixture/proc/merge(datum/gas_mixture/giver)
+ //Purpose: Merges all air from giver into self. Deletes giver.
+ //Called by: Machinery expelling air, check_then_merge, ?
+ //Inputs: The gas to merge.
+ //Outputs: 1
+
+ if(!giver)
+ return 0
+
+ if(abs(temperature-giver.temperature)>MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
+ var/self_heat_capacity = heat_capacity()*group_multiplier
+ var/giver_heat_capacity = giver.heat_capacity()*giver.group_multiplier
+ var/combined_heat_capacity = giver_heat_capacity + self_heat_capacity
+ if(combined_heat_capacity != 0)
+ temperature = (giver.temperature*giver_heat_capacity + temperature*self_heat_capacity)/combined_heat_capacity
+
+ if((group_multiplier>1)||(giver.group_multiplier>1))
+ oxygen += giver.oxygen*giver.group_multiplier/group_multiplier
+ carbon_dioxide += giver.carbon_dioxide*giver.group_multiplier/group_multiplier
+ nitrogen += giver.nitrogen*giver.group_multiplier/group_multiplier
+ toxins += giver.toxins*giver.group_multiplier/group_multiplier
+ else
+ oxygen += giver.oxygen
+ carbon_dioxide += giver.carbon_dioxide
+ nitrogen += giver.nitrogen
+ toxins += giver.toxins
+
+ if(giver.trace_gases.len)
+ for(var/datum/gas/trace_gas in giver.trace_gases)
+ var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases
+ if(!corresponding)
+ corresponding = new trace_gas.type()
+ trace_gases += corresponding
+ corresponding.moles += trace_gas.moles*giver.group_multiplier/group_multiplier
+ update_values()
+
+ // Let the garbage collector handle it, faster according to /tg/ testers
+ //del(giver)
+ return 1
+
+/datum/gas_mixture/proc/remove(amount)
+ //Purpose: Removes a certain number of moles from the air.
+ //Called by: ?
+ //Inputs: How many moles to remove.
+ //Outputs: Removed air.
+
+ var/sum = total_moles()
+ amount = min(amount,sum) //Can not take more air than tile has!
+ if(amount <= 0)
+ return null
+
+ var/datum/gas_mixture/removed = new
+
+
+ removed.oxygen = QUANTIZE((oxygen/sum)*amount)
+ removed.nitrogen = QUANTIZE((nitrogen/sum)*amount)
+ removed.carbon_dioxide = QUANTIZE((carbon_dioxide/sum)*amount)
+ removed.toxins = QUANTIZE((toxins/sum)*amount)
+
+ oxygen -= removed.oxygen/group_multiplier
+ nitrogen -= removed.nitrogen/group_multiplier
+ carbon_dioxide -= removed.carbon_dioxide/group_multiplier
+ toxins -= removed.toxins/group_multiplier
+
+ if(trace_gases.len)
+ for(var/datum/gas/trace_gas in trace_gases)
+ var/datum/gas/corresponding = new trace_gas.type()
+ removed.trace_gases += corresponding
+
+ corresponding.moles = (trace_gas.moles/sum)*amount
+ trace_gas.moles -= corresponding.moles/group_multiplier
+
+ removed.temperature = temperature
+ update_values()
+ removed.update_values()
+
+ return removed
+
+/datum/gas_mixture/proc/remove_ratio(ratio)
+ //Purpose: Removes a certain ratio of the air.
+ //Called by: ?
+ //Inputs: Percentage to remove.
+ //Outputs: Removed air.
+
+ if(ratio <= 0)
+ return null
+
+ ratio = min(ratio, 1)
+
+ var/datum/gas_mixture/removed = new
+
+ removed.oxygen = QUANTIZE(oxygen*ratio)
+ removed.nitrogen = QUANTIZE(nitrogen*ratio)
+ removed.carbon_dioxide = QUANTIZE(carbon_dioxide*ratio)
+ removed.toxins = QUANTIZE(toxins*ratio)
+
+ oxygen -= removed.oxygen/group_multiplier
+ nitrogen -= removed.nitrogen/group_multiplier
+ carbon_dioxide -= removed.carbon_dioxide/group_multiplier
+ toxins -= removed.toxins/group_multiplier
+
+ if(trace_gases.len)
+ for(var/datum/gas/trace_gas in trace_gases)
+ var/datum/gas/corresponding = new trace_gas.type()
+ removed.trace_gases += corresponding
+
+ corresponding.moles = trace_gas.moles*ratio
+ trace_gas.moles -= corresponding.moles/group_multiplier
+
+ removed.temperature = temperature
+ update_values()
+ removed.update_values()
+
+ return removed
+
+/datum/gas_mixture/proc/check_then_remove(amount)
+ //Purpose: Similar to remove(...) but first checks to see if the amount of air removed is small enough
+ // that group processing is still accurate for source (aborts if not)
+ //Called by: ?
+ //Inputs: Number of moles to remove
+ //Outputs: Removed air or 0 if it can remove air or not.
+
+ amount = min(amount,total_moles()) //Can not take more air than tile has!
+
+ if((amount > MINIMUM_AIR_RATIO_TO_SUSPEND) && (amount > total_moles()*MINIMUM_AIR_RATIO_TO_SUSPEND))
+ return 0
+
+ return remove(amount)
+
+/datum/gas_mixture/proc/copy_from(datum/gas_mixture/sample)
+ //Purpose: Duplicates the sample air mixture.
+ //Called by: airgroups splitting, ?
+ //Inputs: Gas to copy
+ //Outputs: 1
+
+ oxygen = sample.oxygen
+ carbon_dioxide = sample.carbon_dioxide
+ nitrogen = sample.nitrogen
+ toxins = sample.toxins
+ total_moles = sample.total_moles()
+
+ trace_gases.len=null
+ if(sample.trace_gases.len > 0)
+ for(var/datum/gas/trace_gas in sample.trace_gases)
+ var/datum/gas/corresponding = new trace_gas.type()
+ trace_gases += corresponding
+
+ corresponding.moles = trace_gas.moles
+
+ temperature = sample.temperature
+
+ return 1
+
+/datum/gas_mixture/proc/check_gas_mixture(datum/gas_mixture/sharer)
+ //Purpose: Telling if one or both airgroups needs to disable group processing.
+ //Called by: Airgroups sharing air, checking if group processing needs disabled.
+ //Inputs: Gas to compare from other airgroup
+ //Outputs: 0 if the self-check failed (local airgroup breaks?)
+ // then -1 if sharer-check failed (sharing airgroup breaks?)
+ // then 1 if both checks pass (share succesful?)
+ if(!istype(sharer))
+ return
+
+ var/delta_oxygen = QUANTIZE(oxygen_archived - sharer.oxygen_archived)/TRANSFER_FRACTION
+ var/delta_carbon_dioxide = QUANTIZE(carbon_dioxide_archived - sharer.carbon_dioxide_archived)/TRANSFER_FRACTION
+ var/delta_nitrogen = QUANTIZE(nitrogen_archived - sharer.nitrogen_archived)/TRANSFER_FRACTION
+ var/delta_toxins = QUANTIZE(toxins_archived - sharer.toxins_archived)/TRANSFER_FRACTION
+
+ var/delta_temperature = (temperature_archived - sharer.temperature_archived)
+
+ if(((abs(delta_oxygen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_oxygen) >= oxygen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
+ || ((abs(delta_carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_carbon_dioxide) >= carbon_dioxide_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
+ || ((abs(delta_nitrogen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_nitrogen) >= nitrogen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
+ || ((abs(delta_toxins) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_toxins) >= toxins_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)))
+ return 0
+
+ if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND)
+ return 0
+
+ if(sharer.trace_gases.len)
+ for(var/datum/gas/trace_gas in sharer.trace_gases)
+ if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND*4)
+ var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases
+ if(corresponding)
+ if(trace_gas.moles_archived >= corresponding.moles_archived*MINIMUM_AIR_RATIO_TO_SUSPEND*4)
return 0
-
- return merge(giver)
-
- proc/merge(datum/gas_mixture/giver)
- //Purpose: Merges all air from giver into self. Deletes giver.
- //Called by: Machinery expelling air, check_then_merge, ?
- //Inputs: The gas to merge.
- //Outputs: 1
-
- if(!giver)
- return 0
-
- if(abs(temperature-giver.temperature)>MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
- var/self_heat_capacity = heat_capacity()*group_multiplier
- var/giver_heat_capacity = giver.heat_capacity()*giver.group_multiplier
- var/combined_heat_capacity = giver_heat_capacity + self_heat_capacity
- if(combined_heat_capacity != 0)
- temperature = (giver.temperature*giver_heat_capacity + temperature*self_heat_capacity)/combined_heat_capacity
-
- if((group_multiplier>1)||(giver.group_multiplier>1))
- oxygen += giver.oxygen*giver.group_multiplier/group_multiplier
- carbon_dioxide += giver.carbon_dioxide*giver.group_multiplier/group_multiplier
- nitrogen += giver.nitrogen*giver.group_multiplier/group_multiplier
- toxins += giver.toxins*giver.group_multiplier/group_multiplier
- else
- oxygen += giver.oxygen
- carbon_dioxide += giver.carbon_dioxide
- nitrogen += giver.nitrogen
- toxins += giver.toxins
-
- if(giver.trace_gases.len)
- for(var/datum/gas/trace_gas in giver.trace_gases)
- var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases
- if(!corresponding)
- corresponding = new trace_gas.type()
- trace_gases += corresponding
- corresponding.moles += trace_gas.moles*giver.group_multiplier/group_multiplier
- update_values()
-
- // Let the garbage collector handle it, faster according to /tg/ testers
- //del(giver)
- return 1
-
- proc/remove(amount)
- //Purpose: Removes a certain number of moles from the air.
- //Called by: ?
- //Inputs: How many moles to remove.
- //Outputs: Removed air.
-
- var/sum = total_moles()
- amount = min(amount,sum) //Can not take more air than tile has!
- if(amount <= 0)
- return null
-
- var/datum/gas_mixture/removed = new
-
-
- removed.oxygen = QUANTIZE((oxygen/sum)*amount)
- removed.nitrogen = QUANTIZE((nitrogen/sum)*amount)
- removed.carbon_dioxide = QUANTIZE((carbon_dioxide/sum)*amount)
- removed.toxins = QUANTIZE((toxins/sum)*amount)
-
- oxygen -= removed.oxygen/group_multiplier
- nitrogen -= removed.nitrogen/group_multiplier
- carbon_dioxide -= removed.carbon_dioxide/group_multiplier
- toxins -= removed.toxins/group_multiplier
-
- if(trace_gases.len)
- for(var/datum/gas/trace_gas in trace_gases)
- var/datum/gas/corresponding = new trace_gas.type()
- removed.trace_gases += corresponding
-
- corresponding.moles = (trace_gas.moles/sum)*amount
- trace_gas.moles -= corresponding.moles/group_multiplier
-
- removed.temperature = temperature
- update_values()
- removed.update_values()
-
- return removed
-
- proc/remove_ratio(ratio)
- //Purpose: Removes a certain ratio of the air.
- //Called by: ?
- //Inputs: Percentage to remove.
- //Outputs: Removed air.
-
- if(ratio <= 0)
- return null
-
- ratio = min(ratio, 1)
-
- var/datum/gas_mixture/removed = new
-
- removed.oxygen = QUANTIZE(oxygen*ratio)
- removed.nitrogen = QUANTIZE(nitrogen*ratio)
- removed.carbon_dioxide = QUANTIZE(carbon_dioxide*ratio)
- removed.toxins = QUANTIZE(toxins*ratio)
-
- oxygen -= removed.oxygen/group_multiplier
- nitrogen -= removed.nitrogen/group_multiplier
- carbon_dioxide -= removed.carbon_dioxide/group_multiplier
- toxins -= removed.toxins/group_multiplier
-
- if(trace_gases.len)
- for(var/datum/gas/trace_gas in trace_gases)
- var/datum/gas/corresponding = new trace_gas.type()
- removed.trace_gases += corresponding
-
- corresponding.moles = trace_gas.moles*ratio
- trace_gas.moles -= corresponding.moles/group_multiplier
-
- removed.temperature = temperature
- update_values()
- removed.update_values()
-
- return removed
-
- proc/check_then_remove(amount)
- //Purpose: Similar to remove(...) but first checks to see if the amount of air removed is small enough
- // that group processing is still accurate for source (aborts if not)
- //Called by: ?
- //Inputs: Number of moles to remove
- //Outputs: Removed air or 0 if it can remove air or not.
-
- amount = min(amount,total_moles()) //Can not take more air than tile has!
-
- if((amount > MINIMUM_AIR_RATIO_TO_SUSPEND) && (amount > total_moles()*MINIMUM_AIR_RATIO_TO_SUSPEND))
- return 0
-
- return remove(amount)
-
- proc/copy_from(datum/gas_mixture/sample)
- //Purpose: Duplicates the sample air mixture.
- //Called by: airgroups splitting, ?
- //Inputs: Gas to copy
- //Outputs: 1
-
- oxygen = sample.oxygen
- carbon_dioxide = sample.carbon_dioxide
- nitrogen = sample.nitrogen
- toxins = sample.toxins
- total_moles = sample.total_moles()
-
- trace_gases.len=null
- if(sample.trace_gases.len > 0)
- for(var/datum/gas/trace_gas in sample.trace_gases)
- var/datum/gas/corresponding = new trace_gas.type()
- trace_gases += corresponding
-
- corresponding.moles = trace_gas.moles
-
- temperature = sample.temperature
-
- return 1
-
- proc/check_gas_mixture(datum/gas_mixture/sharer)
- //Purpose: Telling if one or both airgroups needs to disable group processing.
- //Called by: Airgroups sharing air, checking if group processing needs disabled.
- //Inputs: Gas to compare from other airgroup
- //Outputs: 0 if the self-check failed (local airgroup breaks?)
- // then -1 if sharer-check failed (sharing airgroup breaks?)
- // then 1 if both checks pass (share succesful?)
- if(!istype(sharer))
- return
-
- var/delta_oxygen = QUANTIZE(oxygen_archived - sharer.oxygen_archived)/TRANSFER_FRACTION
- var/delta_carbon_dioxide = QUANTIZE(carbon_dioxide_archived - sharer.carbon_dioxide_archived)/TRANSFER_FRACTION
- var/delta_nitrogen = QUANTIZE(nitrogen_archived - sharer.nitrogen_archived)/TRANSFER_FRACTION
- var/delta_toxins = QUANTIZE(toxins_archived - sharer.toxins_archived)/TRANSFER_FRACTION
-
- var/delta_temperature = (temperature_archived - sharer.temperature_archived)
-
- if(((abs(delta_oxygen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_oxygen) >= oxygen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
- || ((abs(delta_carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_carbon_dioxide) >= carbon_dioxide_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
- || ((abs(delta_nitrogen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_nitrogen) >= nitrogen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
- || ((abs(delta_toxins) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_toxins) >= toxins_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)))
- return 0
-
- if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND)
- return 0
-
- if(sharer.trace_gases.len)
- for(var/datum/gas/trace_gas in sharer.trace_gases)
- if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND*4)
- var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases
- if(corresponding)
- if(trace_gas.moles_archived >= corresponding.moles_archived*MINIMUM_AIR_RATIO_TO_SUSPEND*4)
- return 0
- else
- return 0
-
- if(trace_gases.len)
- for(var/datum/gas/trace_gas in trace_gases)
- if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND*4)
- if(!locate(trace_gas.type) in sharer.trace_gases)
- return 0
-
- if(((abs(delta_oxygen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_oxygen) >= sharer.oxygen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
- || ((abs(delta_carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_carbon_dioxide) >= sharer.carbon_dioxide_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
- || ((abs(delta_nitrogen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_nitrogen) >= sharer.nitrogen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
- || ((abs(delta_toxins) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_toxins) >= sharer.toxins_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)))
- return -1
-
- if(trace_gases.len)
- for(var/datum/gas/trace_gas in trace_gases)
- if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND*4)
- var/datum/gas/corresponding = locate(trace_gas.type) in sharer.trace_gases
- if(corresponding)
- if(trace_gas.moles_archived >= corresponding.moles_archived*MINIMUM_AIR_RATIO_TO_SUSPEND*4)
- return -1
- else
- return -1
-
- return 1
-
- proc/check_turf(turf/model)
- //Purpose: Used to compare the gases in an unsimulated turf with the gas in a simulated one.
- //Called by: Sharing air (mimicing) with adjacent unsimulated turfs
- //Inputs: Unsimulated turf
- //Outputs: 1 if safe to mimic, 0 if needs to break airgroup.
-
- var/delta_oxygen = (oxygen_archived - model.oxygen)/TRANSFER_FRACTION
- var/delta_carbon_dioxide = (carbon_dioxide_archived - model.carbon_dioxide)/TRANSFER_FRACTION
- var/delta_nitrogen = (nitrogen_archived - model.nitrogen)/TRANSFER_FRACTION
- var/delta_toxins = (toxins_archived - model.toxins)/TRANSFER_FRACTION
-
- var/delta_temperature = (temperature_archived - model.temperature)
-
- if(((abs(delta_oxygen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_oxygen) >= oxygen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
- || ((abs(delta_carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_carbon_dioxide) >= carbon_dioxide_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
- || ((abs(delta_nitrogen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_nitrogen) >= nitrogen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
- || ((abs(delta_toxins) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_toxins) >= toxins_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)))
- return 0
- if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND)
- return 0
-
- if(trace_gases.len)
- for(var/datum/gas/trace_gas in trace_gases)
- if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND*4)
- return 0
-
- return 1
-
- proc/share(datum/gas_mixture/sharer)
- //Purpose: Used to transfer gas from a more pressurised tile to a less presurised tile
- // (Two directional, if the other tile is more pressurised, air travels to current tile)
- //Called by: Sharing air with adjacent simulated turfs
- //Inputs: Air datum to share with
- //Outputs: Amount of gas exchanged (Negative if lost air, positive if gained.)
-
-
- if(!istype(sharer))
- return
-
- var/delta_oxygen = QUANTIZE(oxygen_archived - sharer.oxygen_archived)/TRANSFER_FRACTION
- var/delta_carbon_dioxide = QUANTIZE(carbon_dioxide_archived - sharer.carbon_dioxide_archived)/TRANSFER_FRACTION
- var/delta_nitrogen = QUANTIZE(nitrogen_archived - sharer.nitrogen_archived)/TRANSFER_FRACTION
- var/delta_toxins = QUANTIZE(toxins_archived - sharer.toxins_archived)/TRANSFER_FRACTION
-
- var/delta_temperature = (temperature_archived - sharer.temperature_archived)
-
- var/old_self_heat_capacity = 0
- var/old_sharer_heat_capacity = 0
-
- var/heat_self_to_sharer = 0
- var/heat_capacity_self_to_sharer = 0
- var/heat_sharer_to_self = 0
- var/heat_capacity_sharer_to_self = 0
-
- if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
-
- var/delta_air = delta_oxygen+delta_nitrogen
- if(delta_air)
- var/air_heat_capacity = SPECIFIC_HEAT_AIR*delta_air
- if(delta_air > 0)
- heat_self_to_sharer += air_heat_capacity*temperature_archived
- heat_capacity_self_to_sharer += air_heat_capacity
- else
- heat_sharer_to_self -= air_heat_capacity*sharer.temperature_archived
- heat_capacity_sharer_to_self -= air_heat_capacity
-
- if(delta_carbon_dioxide)
- var/carbon_dioxide_heat_capacity = SPECIFIC_HEAT_CDO*delta_carbon_dioxide
- if(delta_carbon_dioxide > 0)
- heat_self_to_sharer += carbon_dioxide_heat_capacity*temperature_archived
- heat_capacity_self_to_sharer += carbon_dioxide_heat_capacity
- else
- heat_sharer_to_self -= carbon_dioxide_heat_capacity*sharer.temperature_archived
- heat_capacity_sharer_to_self -= carbon_dioxide_heat_capacity
-
- if(delta_toxins)
- var/toxins_heat_capacity = SPECIFIC_HEAT_TOXIN*delta_toxins
- if(delta_toxins > 0)
- heat_self_to_sharer += toxins_heat_capacity*temperature_archived
- heat_capacity_self_to_sharer += toxins_heat_capacity
- else
- heat_sharer_to_self -= toxins_heat_capacity*sharer.temperature_archived
- heat_capacity_sharer_to_self -= toxins_heat_capacity
-
- old_self_heat_capacity = heat_capacity()*group_multiplier
- old_sharer_heat_capacity = sharer.heat_capacity()*sharer.group_multiplier
-
- oxygen -= delta_oxygen/group_multiplier
- sharer.oxygen += delta_oxygen/sharer.group_multiplier
-
- carbon_dioxide -= delta_carbon_dioxide/group_multiplier
- sharer.carbon_dioxide += delta_carbon_dioxide/sharer.group_multiplier
-
- nitrogen -= delta_nitrogen/group_multiplier
- sharer.nitrogen += delta_nitrogen/sharer.group_multiplier
-
- toxins -= delta_toxins/group_multiplier
- sharer.toxins += delta_toxins/sharer.group_multiplier
-
- var/moved_moles = (delta_oxygen + delta_carbon_dioxide + delta_nitrogen + delta_toxins)
-
- var/list/trace_types_considered = list()
-
- if(trace_gases.len)
- for(var/datum/gas/trace_gas in trace_gases)
-
- var/datum/gas/corresponding = locate(trace_gas.type) in sharer.trace_gases
- var/delta = 0
-
- if(corresponding)
- delta = QUANTIZE(trace_gas.moles_archived - corresponding.moles_archived)/TRANSFER_FRACTION
- else
- corresponding = new trace_gas.type()
- sharer.trace_gases += corresponding
-
- delta = trace_gas.moles_archived/TRANSFER_FRACTION
-
- trace_gas.moles -= delta/group_multiplier
- corresponding.moles += delta/sharer.group_multiplier
-
- if(delta)
- var/individual_heat_capacity = trace_gas.specific_heat*delta
- if(delta > 0)
- heat_self_to_sharer += individual_heat_capacity*temperature_archived
- heat_capacity_self_to_sharer += individual_heat_capacity
- else
- heat_sharer_to_self -= individual_heat_capacity*sharer.temperature_archived
- heat_capacity_sharer_to_self -= individual_heat_capacity
-
- moved_moles += delta
-
- trace_types_considered += trace_gas.type
-
-
- if(sharer.trace_gases.len)
- for(var/datum/gas/trace_gas in sharer.trace_gases)
- if(trace_gas.type in trace_types_considered) continue
- else
- var/datum/gas/corresponding
- var/delta = 0
-
- corresponding = new trace_gas.type()
- trace_gases += corresponding
-
- delta = trace_gas.moles_archived/TRANSFER_FRACTION
-
- trace_gas.moles -= delta/sharer.group_multiplier
- corresponding.moles += delta/group_multiplier
-
- //Guaranteed transfer from sharer to self
- var/individual_heat_capacity = trace_gas.specific_heat*delta
- heat_sharer_to_self += individual_heat_capacity*sharer.temperature_archived
- heat_capacity_sharer_to_self += individual_heat_capacity
-
- moved_moles += -delta
- update_values()
- sharer.update_values()
-
- if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
- var/new_self_heat_capacity = old_self_heat_capacity + heat_capacity_sharer_to_self - heat_capacity_self_to_sharer
- var/new_sharer_heat_capacity = old_sharer_heat_capacity + heat_capacity_self_to_sharer - heat_capacity_sharer_to_self
-
- if(new_self_heat_capacity > MINIMUM_HEAT_CAPACITY)
- temperature = (old_self_heat_capacity*temperature - heat_capacity_self_to_sharer*temperature_archived + heat_capacity_sharer_to_self*sharer.temperature_archived)/new_self_heat_capacity
-
- if(new_sharer_heat_capacity > MINIMUM_HEAT_CAPACITY)
- sharer.temperature = (old_sharer_heat_capacity*sharer.temperature-heat_capacity_sharer_to_self*sharer.temperature_archived + heat_capacity_self_to_sharer*temperature_archived)/new_sharer_heat_capacity
-
- if(abs(old_sharer_heat_capacity) > MINIMUM_HEAT_CAPACITY)
- if(abs(new_sharer_heat_capacity/old_sharer_heat_capacity - 1) < 0.10) // <10% change in sharer heat capacity
- temperature_share(sharer, OPEN_HEAT_TRANSFER_COEFFICIENT)
-
- if((delta_temperature > MINIMUM_TEMPERATURE_TO_MOVE) || abs(moved_moles) > MINIMUM_MOLES_DELTA_TO_MOVE)
- var/delta_pressure = temperature_archived*(total_moles() + moved_moles) - sharer.temperature_archived*(sharer.total_moles() - moved_moles)
- return delta_pressure*R_IDEAL_GAS_EQUATION/volume
-
- else
- return 0
-
- proc/mimic(turf/model, border_multiplier)
- //Purpose: Used transfer gas from a more pressurised tile to a less presurised unsimulated tile.
- //Called by: "sharing" from unsimulated to simulated turfs.
- //Inputs: Unsimulated turf, Multiplier for gas transfer (optional)
- //Outputs: Amount of gas exchanged
-
- var/delta_oxygen = QUANTIZE(oxygen_archived - model.oxygen)/TRANSFER_FRACTION
- var/delta_carbon_dioxide = QUANTIZE(carbon_dioxide_archived - model.carbon_dioxide)/TRANSFER_FRACTION
- var/delta_nitrogen = QUANTIZE(nitrogen_archived - model.nitrogen)/TRANSFER_FRACTION
- var/delta_toxins = QUANTIZE(toxins_archived - model.toxins)/TRANSFER_FRACTION
-
- var/delta_temperature = (temperature_archived - model.temperature)
-
- var/heat_transferred = 0
- var/old_self_heat_capacity = 0
- var/heat_capacity_transferred = 0
-
- if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
-
- var/delta_air = delta_oxygen+delta_nitrogen
- if(delta_air)
- var/air_heat_capacity = SPECIFIC_HEAT_AIR*delta_air
- heat_transferred -= air_heat_capacity*model.temperature
- heat_capacity_transferred -= air_heat_capacity
-
- if(delta_carbon_dioxide)
- var/carbon_dioxide_heat_capacity = SPECIFIC_HEAT_CDO*delta_carbon_dioxide
- heat_transferred -= carbon_dioxide_heat_capacity*model.temperature
- heat_capacity_transferred -= carbon_dioxide_heat_capacity
-
- if(delta_toxins)
- var/toxins_heat_capacity = SPECIFIC_HEAT_TOXIN*delta_toxins
- heat_transferred -= toxins_heat_capacity*model.temperature
- heat_capacity_transferred -= toxins_heat_capacity
-
- old_self_heat_capacity = heat_capacity()*group_multiplier
-
- if(border_multiplier)
- oxygen -= delta_oxygen*border_multiplier/group_multiplier
- carbon_dioxide -= delta_carbon_dioxide*border_multiplier/group_multiplier
- nitrogen -= delta_nitrogen*border_multiplier/group_multiplier
- toxins -= delta_toxins*border_multiplier/group_multiplier
- else
- oxygen -= delta_oxygen/group_multiplier
- carbon_dioxide -= delta_carbon_dioxide/group_multiplier
- nitrogen -= delta_nitrogen/group_multiplier
- toxins -= delta_toxins/group_multiplier
-
- var/moved_moles = (delta_oxygen + delta_carbon_dioxide + delta_nitrogen + delta_toxins)
-
- if(trace_gases.len)
- for(var/datum/gas/trace_gas in trace_gases)
- var/delta = 0
-
- delta = trace_gas.moles_archived/TRANSFER_FRACTION
-
- if(border_multiplier)
- trace_gas.moles -= delta*border_multiplier/group_multiplier
- else
- trace_gas.moles -= delta/group_multiplier
-
- var/heat_cap_transferred = delta*trace_gas.specific_heat
- heat_transferred += heat_cap_transferred*temperature_archived
- heat_capacity_transferred += heat_cap_transferred
- moved_moles += delta
- update_values()
-
- if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
- var/new_self_heat_capacity = old_self_heat_capacity - heat_capacity_transferred
- if(new_self_heat_capacity > MINIMUM_HEAT_CAPACITY)
- if(border_multiplier)
- temperature = (old_self_heat_capacity*temperature - heat_capacity_transferred*border_multiplier*temperature_archived)/new_self_heat_capacity
- else
- temperature = (old_self_heat_capacity*temperature - heat_capacity_transferred*border_multiplier*temperature_archived)/new_self_heat_capacity
-
- temperature_mimic(model, model.thermal_conductivity, border_multiplier)
-
- if((delta_temperature > MINIMUM_TEMPERATURE_TO_MOVE) || abs(moved_moles) > MINIMUM_MOLES_DELTA_TO_MOVE)
- var/delta_pressure = temperature_archived*(total_moles() + moved_moles) - model.temperature*(model.oxygen+model.carbon_dioxide+model.nitrogen+model.toxins)
- return delta_pressure*R_IDEAL_GAS_EQUATION/volume
- else
- return 0
-
- proc/check_both_then_temperature_share(datum/gas_mixture/sharer, conduction_coefficient)
- var/delta_temperature = (temperature_archived - sharer.temperature_archived)
-
- var/self_heat_capacity = heat_capacity_archived()
- var/sharer_heat_capacity = sharer.heat_capacity_archived()
-
- var/self_temperature_delta = 0
- var/sharer_temperature_delta = 0
-
- if((sharer_heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY))
- var/heat = conduction_coefficient*delta_temperature* \
- (self_heat_capacity*sharer_heat_capacity/(self_heat_capacity+sharer_heat_capacity))
-
- self_temperature_delta = -heat/(self_heat_capacity*group_multiplier)
- sharer_temperature_delta = heat/(sharer_heat_capacity*sharer.group_multiplier)
- else
- return 1
-
- if((abs(self_temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) \
- && (abs(self_temperature_delta) > MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND*temperature_archived))
- return 0
-
- if((abs(sharer_temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) \
- && (abs(sharer_temperature_delta) > MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND*sharer.temperature_archived))
- return -1
-
- temperature += self_temperature_delta
- sharer.temperature += sharer_temperature_delta
-
- return 1
- //Logic integrated from: temperature_share(sharer, conduction_coefficient) for efficiency
-
- proc/check_me_then_temperature_share(datum/gas_mixture/sharer, conduction_coefficient)
- var/delta_temperature = (temperature_archived - sharer.temperature_archived)
-
- var/self_heat_capacity = heat_capacity_archived()
- var/sharer_heat_capacity = sharer.heat_capacity_archived()
-
- var/self_temperature_delta = 0
- var/sharer_temperature_delta = 0
-
- if((sharer_heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY))
- var/heat = conduction_coefficient*delta_temperature* \
- (self_heat_capacity*sharer_heat_capacity/(self_heat_capacity+sharer_heat_capacity))
-
- self_temperature_delta = -heat/(self_heat_capacity*group_multiplier)
- sharer_temperature_delta = heat/(sharer_heat_capacity*sharer.group_multiplier)
- else
- return 1
-
- if((abs(self_temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) \
- && (abs(self_temperature_delta) > MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND*temperature_archived))
- return 0
-
- temperature += self_temperature_delta
- sharer.temperature += sharer_temperature_delta
-
- return 1
- //Logic integrated from: temperature_share(sharer, conduction_coefficient) for efficiency
-
- proc/check_me_then_temperature_turf_share(turf/simulated/sharer, conduction_coefficient)
- var/delta_temperature = (temperature_archived - sharer.temperature)
-
- var/self_temperature_delta = 0
- var/sharer_temperature_delta = 0
-
- if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
- var/self_heat_capacity = heat_capacity_archived()
-
- if((sharer.heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY))
- var/heat = conduction_coefficient*delta_temperature* \
- (self_heat_capacity*sharer.heat_capacity/(self_heat_capacity+sharer.heat_capacity))
-
- self_temperature_delta = -heat/(self_heat_capacity*group_multiplier)
- sharer_temperature_delta = heat/sharer.heat_capacity
- else
- return 1
-
- if((abs(self_temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) \
- && (abs(self_temperature_delta) > MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND*temperature_archived))
- return 0
-
- temperature += self_temperature_delta
- sharer.temperature += sharer_temperature_delta
-
- return 1
- //Logic integrated from: temperature_turf_share(sharer, conduction_coefficient) for efficiency
-
- proc/check_me_then_temperature_mimic(turf/model, conduction_coefficient)
- var/delta_temperature = (temperature_archived - model.temperature)
- var/self_temperature_delta = 0
-
- if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
- var/self_heat_capacity = heat_capacity_archived()
-
- if((model.heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY))
- var/heat = conduction_coefficient*delta_temperature* \
- (self_heat_capacity*model.heat_capacity/(self_heat_capacity+model.heat_capacity))
-
- self_temperature_delta = -heat/(self_heat_capacity*group_multiplier)
-
- if((abs(self_temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) \
- && (abs(self_temperature_delta) > MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND*temperature_archived))
- return 0
-
- temperature += self_temperature_delta
-
- return 1
- //Logic integrated from: temperature_mimic(model, conduction_coefficient) for efficiency
-
- proc/temperature_share(datum/gas_mixture/sharer, conduction_coefficient)
-
- var/delta_temperature = (temperature_archived - sharer.temperature_archived)
- if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
- var/self_heat_capacity = heat_capacity_archived()
- var/sharer_heat_capacity = sharer.heat_capacity_archived()
- if(!group_multiplier)
- message_admins("Error! The gas mixture (ref \ref[src]) has no group multiplier!")
- return
-
- if((sharer_heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY))
- var/heat = conduction_coefficient*delta_temperature* \
- (self_heat_capacity*sharer_heat_capacity/(self_heat_capacity+sharer_heat_capacity))
-
- temperature -= heat/(self_heat_capacity*group_multiplier)
- sharer.temperature += heat/(sharer_heat_capacity*sharer.group_multiplier)
-
- proc/temperature_mimic(turf/model, conduction_coefficient, border_multiplier)
- var/delta_temperature = (temperature - model.temperature)
- if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
- var/self_heat_capacity = heat_capacity()//_archived()
- if(!group_multiplier)
- message_admins("Error! The gas mixture (ref \ref[src]) has no group multiplier!")
- return
-
- if((model.heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY))
- var/heat = conduction_coefficient*delta_temperature* \
- (self_heat_capacity*model.heat_capacity/(self_heat_capacity+model.heat_capacity))
-
- if(border_multiplier)
- temperature -= heat*border_multiplier/(self_heat_capacity*group_multiplier)
- else
- temperature -= heat/(self_heat_capacity*group_multiplier)
-
- proc/temperature_turf_share(turf/simulated/sharer, conduction_coefficient)
- var/delta_temperature = (temperature_archived - sharer.temperature)
- if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
- var/self_heat_capacity = heat_capacity()
-
- if((sharer.heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY))
- var/heat = conduction_coefficient*delta_temperature* \
- (self_heat_capacity*sharer.heat_capacity/(self_heat_capacity+sharer.heat_capacity))
-
- temperature -= heat/(self_heat_capacity*group_multiplier)
- sharer.temperature += heat/sharer.heat_capacity
-
- proc/compare(datum/gas_mixture/sample)
- //Purpose: Compares sample to self to see if within acceptable ranges that group processing may be enabled
- //Called by: Airgroups trying to rebuild
- //Inputs: Gas mix to compare
- //Outputs: 1 if can rebuild, 0 if not.
- if(!sample) return 0
-
- if((abs(oxygen-sample.oxygen) > MINIMUM_AIR_TO_SUSPEND) && \
- ((oxygen < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.oxygen) || (oxygen > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.oxygen)))
- return 0
- if((abs(nitrogen-sample.nitrogen) > MINIMUM_AIR_TO_SUSPEND) && \
- ((nitrogen < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.nitrogen) || (nitrogen > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.nitrogen)))
- return 0
- if((abs(carbon_dioxide-sample.carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && \
- ((carbon_dioxide < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.carbon_dioxide) || (oxygen > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.carbon_dioxide)))
- return 0
- if((abs(toxins-sample.toxins) > MINIMUM_AIR_TO_SUSPEND) && \
- ((toxins < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.toxins) || (toxins > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.toxins)))
- return 0
-
- if(total_moles() > MINIMUM_AIR_TO_SUSPEND)
- if((abs(temperature-sample.temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) && \
- ((temperature < (1-MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND)*sample.temperature) || (temperature > (1+MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND)*sample.temperature)))
- //world << "temp fail [temperature] & [sample.temperature]"
+ else
return 0
- if(sample.trace_gases.len)
- for(var/datum/gas/trace_gas in sample.trace_gases)
- if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND)
- var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases
- if(corresponding)
- if((abs(trace_gas.moles - corresponding.moles) > MINIMUM_AIR_TO_SUSPEND) && \
- ((corresponding.moles < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*trace_gas.moles) || (corresponding.moles > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*trace_gas.moles)))
- return 0
- else
- return 0
+ if(trace_gases.len)
+ for(var/datum/gas/trace_gas in trace_gases)
+ if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND*4)
+ if(!locate(trace_gas.type) in sharer.trace_gases)
+ return 0
- if(trace_gases.len)
- for(var/datum/gas/trace_gas in trace_gases)
- if(trace_gas.moles > MINIMUM_AIR_TO_SUSPEND)
- var/datum/gas/corresponding = locate(trace_gas.type) in sample.trace_gases
- if(corresponding)
- if((abs(trace_gas.moles - corresponding.moles) > MINIMUM_AIR_TO_SUSPEND) && \
- ((trace_gas.moles < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*corresponding.moles) || (trace_gas.moles > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*corresponding.moles)))
- return 0
- else
- return 0
- return 1
+ if(((abs(delta_oxygen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_oxygen) >= sharer.oxygen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
+ || ((abs(delta_carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_carbon_dioxide) >= sharer.carbon_dioxide_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
+ || ((abs(delta_nitrogen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_nitrogen) >= sharer.nitrogen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
+ || ((abs(delta_toxins) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_toxins) >= sharer.toxins_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)))
+ return -1
+
+ if(trace_gases.len)
+ for(var/datum/gas/trace_gas in trace_gases)
+ if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND*4)
+ var/datum/gas/corresponding = locate(trace_gas.type) in sharer.trace_gases
+ if(corresponding)
+ if(trace_gas.moles_archived >= corresponding.moles_archived*MINIMUM_AIR_RATIO_TO_SUSPEND*4)
+ return -1
+ else
+ return -1
+
+ return 1
+
+/datum/gas_mixture/proc/check_turf(turf/model)
+ //Purpose: Used to compare the gases in an unsimulated turf with the gas in a simulated one.
+ //Called by: Sharing air (mimicing) with adjacent unsimulated turfs
+ //Inputs: Unsimulated turf
+ //Outputs: 1 if safe to mimic, 0 if needs to break airgroup.
+
+ var/delta_oxygen = (oxygen_archived - model.oxygen)/TRANSFER_FRACTION
+ var/delta_carbon_dioxide = (carbon_dioxide_archived - model.carbon_dioxide)/TRANSFER_FRACTION
+ var/delta_nitrogen = (nitrogen_archived - model.nitrogen)/TRANSFER_FRACTION
+ var/delta_toxins = (toxins_archived - model.toxins)/TRANSFER_FRACTION
+
+ var/delta_temperature = (temperature_archived - model.temperature)
+
+ if(((abs(delta_oxygen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_oxygen) >= oxygen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
+ || ((abs(delta_carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_carbon_dioxide) >= carbon_dioxide_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
+ || ((abs(delta_nitrogen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_nitrogen) >= nitrogen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
+ || ((abs(delta_toxins) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_toxins) >= toxins_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)))
+ return 0
+ if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND)
+ return 0
+
+ if(trace_gases.len)
+ for(var/datum/gas/trace_gas in trace_gases)
+ if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND*4)
+ return 0
+
+ return 1
+
+/datum/gas_mixture/proc/share(datum/gas_mixture/sharer)
+ //Purpose: Used to transfer gas from a more pressurised tile to a less presurised tile
+ // (Two directional, if the other tile is more pressurised, air travels to current tile)
+ //Called by: Sharing air with adjacent simulated turfs
+ //Inputs: Air datum to share with
+ //Outputs: Amount of gas exchanged (Negative if lost air, positive if gained.)
- 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
+ if(!istype(sharer))
+ return
- oxygen -= right_side.oxygen
- carbon_dioxide -= right_side.carbon_dioxide
- nitrogen -= right_side.nitrogen
- toxins -= right_side.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
- 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
+ var/delta_temperature = (temperature_archived - sharer.temperature_archived)
- corresponding.moles -= trace_gas.moles
- update_values()
- return 1
\ No newline at end of file
+ var/old_self_heat_capacity = 0
+ var/old_sharer_heat_capacity = 0
+
+ var/heat_self_to_sharer = 0
+ var/heat_capacity_self_to_sharer = 0
+ var/heat_sharer_to_self = 0
+ var/heat_capacity_sharer_to_self = 0
+
+ if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
+
+ var/delta_air = delta_oxygen+delta_nitrogen
+ if(delta_air)
+ var/air_heat_capacity = SPECIFIC_HEAT_AIR*delta_air
+ if(delta_air > 0)
+ heat_self_to_sharer += air_heat_capacity*temperature_archived
+ heat_capacity_self_to_sharer += air_heat_capacity
+ else
+ heat_sharer_to_self -= air_heat_capacity*sharer.temperature_archived
+ heat_capacity_sharer_to_self -= air_heat_capacity
+
+ if(delta_carbon_dioxide)
+ var/carbon_dioxide_heat_capacity = SPECIFIC_HEAT_CDO*delta_carbon_dioxide
+ if(delta_carbon_dioxide > 0)
+ heat_self_to_sharer += carbon_dioxide_heat_capacity*temperature_archived
+ heat_capacity_self_to_sharer += carbon_dioxide_heat_capacity
+ else
+ heat_sharer_to_self -= carbon_dioxide_heat_capacity*sharer.temperature_archived
+ heat_capacity_sharer_to_self -= carbon_dioxide_heat_capacity
+
+ if(delta_toxins)
+ var/toxins_heat_capacity = SPECIFIC_HEAT_TOXIN*delta_toxins
+ if(delta_toxins > 0)
+ heat_self_to_sharer += toxins_heat_capacity*temperature_archived
+ heat_capacity_self_to_sharer += toxins_heat_capacity
+ else
+ heat_sharer_to_self -= toxins_heat_capacity*sharer.temperature_archived
+ heat_capacity_sharer_to_self -= toxins_heat_capacity
+
+ old_self_heat_capacity = heat_capacity()*group_multiplier
+ old_sharer_heat_capacity = sharer.heat_capacity()*sharer.group_multiplier
+
+ oxygen -= delta_oxygen/group_multiplier
+ sharer.oxygen += delta_oxygen/sharer.group_multiplier
+
+ carbon_dioxide -= delta_carbon_dioxide/group_multiplier
+ sharer.carbon_dioxide += delta_carbon_dioxide/sharer.group_multiplier
+
+ nitrogen -= delta_nitrogen/group_multiplier
+ sharer.nitrogen += delta_nitrogen/sharer.group_multiplier
+
+ toxins -= delta_toxins/group_multiplier
+ sharer.toxins += delta_toxins/sharer.group_multiplier
+
+ var/moved_moles = (delta_oxygen + delta_carbon_dioxide + delta_nitrogen + delta_toxins)
+
+ var/list/trace_types_considered = list()
+
+ if(trace_gases.len)
+ for(var/datum/gas/trace_gas in trace_gases)
+
+ var/datum/gas/corresponding = locate(trace_gas.type) in sharer.trace_gases
+ var/delta = 0
+
+ if(corresponding)
+ delta = QUANTIZE(trace_gas.moles_archived - corresponding.moles_archived)/TRANSFER_FRACTION
+ else
+ corresponding = new trace_gas.type()
+ sharer.trace_gases += corresponding
+
+ delta = trace_gas.moles_archived/TRANSFER_FRACTION
+
+ trace_gas.moles -= delta/group_multiplier
+ corresponding.moles += delta/sharer.group_multiplier
+
+ if(delta)
+ var/individual_heat_capacity = trace_gas.specific_heat*delta
+ if(delta > 0)
+ heat_self_to_sharer += individual_heat_capacity*temperature_archived
+ heat_capacity_self_to_sharer += individual_heat_capacity
+ else
+ heat_sharer_to_self -= individual_heat_capacity*sharer.temperature_archived
+ heat_capacity_sharer_to_self -= individual_heat_capacity
+
+ moved_moles += delta
+
+ trace_types_considered += trace_gas.type
+
+
+ if(sharer.trace_gases.len)
+ for(var/datum/gas/trace_gas in sharer.trace_gases)
+ if(trace_gas.type in trace_types_considered) continue
+ else
+ var/datum/gas/corresponding
+ var/delta = 0
+
+ corresponding = new trace_gas.type()
+ trace_gases += corresponding
+
+ delta = trace_gas.moles_archived/TRANSFER_FRACTION
+
+ trace_gas.moles -= delta/sharer.group_multiplier
+ corresponding.moles += delta/group_multiplier
+
+ //Guaranteed transfer from sharer to self
+ var/individual_heat_capacity = trace_gas.specific_heat*delta
+ heat_sharer_to_self += individual_heat_capacity*sharer.temperature_archived
+ heat_capacity_sharer_to_self += individual_heat_capacity
+
+ moved_moles += -delta
+ update_values()
+ sharer.update_values()
+
+ if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
+ var/new_self_heat_capacity = old_self_heat_capacity + heat_capacity_sharer_to_self - heat_capacity_self_to_sharer
+ var/new_sharer_heat_capacity = old_sharer_heat_capacity + heat_capacity_self_to_sharer - heat_capacity_sharer_to_self
+
+ if(new_self_heat_capacity > MINIMUM_HEAT_CAPACITY)
+ temperature = (old_self_heat_capacity*temperature - heat_capacity_self_to_sharer*temperature_archived + heat_capacity_sharer_to_self*sharer.temperature_archived)/new_self_heat_capacity
+
+ if(new_sharer_heat_capacity > MINIMUM_HEAT_CAPACITY)
+ sharer.temperature = (old_sharer_heat_capacity*sharer.temperature-heat_capacity_sharer_to_self*sharer.temperature_archived + heat_capacity_self_to_sharer*temperature_archived)/new_sharer_heat_capacity
+
+ if(abs(old_sharer_heat_capacity) > MINIMUM_HEAT_CAPACITY)
+ if(abs(new_sharer_heat_capacity/old_sharer_heat_capacity - 1) < 0.10) // <10% change in sharer heat capacity
+ temperature_share(sharer, OPEN_HEAT_TRANSFER_COEFFICIENT)
+
+ if((delta_temperature > MINIMUM_TEMPERATURE_TO_MOVE) || abs(moved_moles) > MINIMUM_MOLES_DELTA_TO_MOVE)
+ var/delta_pressure = temperature_archived*(total_moles() + moved_moles) - sharer.temperature_archived*(sharer.total_moles() - moved_moles)
+ return delta_pressure*R_IDEAL_GAS_EQUATION/volume
+
+ else
+ return 0
+
+/datum/gas_mixture/proc/mimic(turf/model, border_multiplier)
+ //Purpose: Used transfer gas from a more pressurised tile to a less presurised unsimulated tile.
+ //Called by: "sharing" from unsimulated to simulated turfs.
+ //Inputs: Unsimulated turf, Multiplier for gas transfer (optional)
+ //Outputs: Amount of gas exchanged
+
+ var/delta_oxygen = QUANTIZE(oxygen_archived - model.oxygen)/TRANSFER_FRACTION
+ var/delta_carbon_dioxide = QUANTIZE(carbon_dioxide_archived - model.carbon_dioxide)/TRANSFER_FRACTION
+ var/delta_nitrogen = QUANTIZE(nitrogen_archived - model.nitrogen)/TRANSFER_FRACTION
+ var/delta_toxins = QUANTIZE(toxins_archived - model.toxins)/TRANSFER_FRACTION
+
+ var/delta_temperature = (temperature_archived - model.temperature)
+
+ var/heat_transferred = 0
+ var/old_self_heat_capacity = 0
+ var/heat_capacity_transferred = 0
+
+ if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
+
+ var/delta_air = delta_oxygen+delta_nitrogen
+ if(delta_air)
+ var/air_heat_capacity = SPECIFIC_HEAT_AIR*delta_air
+ heat_transferred -= air_heat_capacity*model.temperature
+ heat_capacity_transferred -= air_heat_capacity
+
+ if(delta_carbon_dioxide)
+ var/carbon_dioxide_heat_capacity = SPECIFIC_HEAT_CDO*delta_carbon_dioxide
+ heat_transferred -= carbon_dioxide_heat_capacity*model.temperature
+ heat_capacity_transferred -= carbon_dioxide_heat_capacity
+
+ if(delta_toxins)
+ var/toxins_heat_capacity = SPECIFIC_HEAT_TOXIN*delta_toxins
+ heat_transferred -= toxins_heat_capacity*model.temperature
+ heat_capacity_transferred -= toxins_heat_capacity
+
+ old_self_heat_capacity = heat_capacity()*group_multiplier
+
+ if(border_multiplier)
+ oxygen -= delta_oxygen*border_multiplier/group_multiplier
+ carbon_dioxide -= delta_carbon_dioxide*border_multiplier/group_multiplier
+ nitrogen -= delta_nitrogen*border_multiplier/group_multiplier
+ toxins -= delta_toxins*border_multiplier/group_multiplier
+ else
+ oxygen -= delta_oxygen/group_multiplier
+ carbon_dioxide -= delta_carbon_dioxide/group_multiplier
+ nitrogen -= delta_nitrogen/group_multiplier
+ toxins -= delta_toxins/group_multiplier
+
+ var/moved_moles = (delta_oxygen + delta_carbon_dioxide + delta_nitrogen + delta_toxins)
+
+ if(trace_gases.len)
+ for(var/datum/gas/trace_gas in trace_gases)
+ var/delta = 0
+
+ delta = trace_gas.moles_archived/TRANSFER_FRACTION
+
+ if(border_multiplier)
+ trace_gas.moles -= delta*border_multiplier/group_multiplier
+ else
+ trace_gas.moles -= delta/group_multiplier
+
+ var/heat_cap_transferred = delta*trace_gas.specific_heat
+ heat_transferred += heat_cap_transferred*temperature_archived
+ heat_capacity_transferred += heat_cap_transferred
+ moved_moles += delta
+ update_values()
+
+ if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
+ var/new_self_heat_capacity = old_self_heat_capacity - heat_capacity_transferred
+ if(new_self_heat_capacity > MINIMUM_HEAT_CAPACITY)
+ if(border_multiplier)
+ temperature = (old_self_heat_capacity*temperature - heat_capacity_transferred*border_multiplier*temperature_archived)/new_self_heat_capacity
+ else
+ temperature = (old_self_heat_capacity*temperature - heat_capacity_transferred*border_multiplier*temperature_archived)/new_self_heat_capacity
+
+ temperature_mimic(model, model.thermal_conductivity, border_multiplier)
+
+ if((delta_temperature > MINIMUM_TEMPERATURE_TO_MOVE) || abs(moved_moles) > MINIMUM_MOLES_DELTA_TO_MOVE)
+ var/delta_pressure = temperature_archived*(total_moles() + moved_moles) - model.temperature*(model.oxygen+model.carbon_dioxide+model.nitrogen+model.toxins)
+ return delta_pressure*R_IDEAL_GAS_EQUATION/volume
+ else
+ return 0
+
+/datum/gas_mixture/proc/check_both_then_temperature_share(datum/gas_mixture/sharer, conduction_coefficient)
+ var/delta_temperature = (temperature_archived - sharer.temperature_archived)
+
+ var/self_heat_capacity = heat_capacity_archived()
+ var/sharer_heat_capacity = sharer.heat_capacity_archived()
+
+ var/self_temperature_delta = 0
+ var/sharer_temperature_delta = 0
+
+ if((sharer_heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY))
+ var/heat = conduction_coefficient*delta_temperature* \
+ (self_heat_capacity*sharer_heat_capacity/(self_heat_capacity+sharer_heat_capacity))
+
+ self_temperature_delta = -heat/(self_heat_capacity*group_multiplier)
+ sharer_temperature_delta = heat/(sharer_heat_capacity*sharer.group_multiplier)
+ else
+ return 1
+
+ if((abs(self_temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) \
+ && (abs(self_temperature_delta) > MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND*temperature_archived))
+ return 0
+
+ if((abs(sharer_temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) \
+ && (abs(sharer_temperature_delta) > MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND*sharer.temperature_archived))
+ return -1
+
+ temperature += self_temperature_delta
+ sharer.temperature += sharer_temperature_delta
+
+ return 1
+ //Logic integrated from: temperature_share(sharer, conduction_coefficient) for efficiency
+
+/datum/gas_mixture/proc/check_me_then_temperature_share(datum/gas_mixture/sharer, conduction_coefficient)
+ var/delta_temperature = (temperature_archived - sharer.temperature_archived)
+
+ var/self_heat_capacity = heat_capacity_archived()
+ var/sharer_heat_capacity = sharer.heat_capacity_archived()
+
+ var/self_temperature_delta = 0
+ var/sharer_temperature_delta = 0
+
+ if((sharer_heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY))
+ var/heat = conduction_coefficient*delta_temperature* \
+ (self_heat_capacity*sharer_heat_capacity/(self_heat_capacity+sharer_heat_capacity))
+
+ self_temperature_delta = -heat/(self_heat_capacity*group_multiplier)
+ sharer_temperature_delta = heat/(sharer_heat_capacity*sharer.group_multiplier)
+ else
+ return 1
+
+ if((abs(self_temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) \
+ && (abs(self_temperature_delta) > MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND*temperature_archived))
+ return 0
+
+ temperature += self_temperature_delta
+ sharer.temperature += sharer_temperature_delta
+
+ return 1
+ //Logic integrated from: temperature_share(sharer, conduction_coefficient) for efficiency
+
+/datum/gas_mixture/proc/check_me_then_temperature_turf_share(turf/simulated/sharer, conduction_coefficient)
+ var/delta_temperature = (temperature_archived - sharer.temperature)
+
+ var/self_temperature_delta = 0
+ var/sharer_temperature_delta = 0
+
+ if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
+ var/self_heat_capacity = heat_capacity_archived()
+
+ if((sharer.heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY))
+ var/heat = conduction_coefficient*delta_temperature* \
+ (self_heat_capacity*sharer.heat_capacity/(self_heat_capacity+sharer.heat_capacity))
+
+ self_temperature_delta = -heat/(self_heat_capacity*group_multiplier)
+ sharer_temperature_delta = heat/sharer.heat_capacity
+ else
+ return 1
+
+ if((abs(self_temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) \
+ && (abs(self_temperature_delta) > MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND*temperature_archived))
+ return 0
+
+ temperature += self_temperature_delta
+ sharer.temperature += sharer_temperature_delta
+
+ return 1
+ //Logic integrated from: temperature_turf_share(sharer, conduction_coefficient) for efficiency
+
+/datum/gas_mixture/proc/check_me_then_temperature_mimic(turf/model, conduction_coefficient)
+ var/delta_temperature = (temperature_archived - model.temperature)
+ var/self_temperature_delta = 0
+
+ if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
+ var/self_heat_capacity = heat_capacity_archived()
+
+ if((model.heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY))
+ var/heat = conduction_coefficient*delta_temperature* \
+ (self_heat_capacity*model.heat_capacity/(self_heat_capacity+model.heat_capacity))
+
+ self_temperature_delta = -heat/(self_heat_capacity*group_multiplier)
+
+ if((abs(self_temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) \
+ && (abs(self_temperature_delta) > MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND*temperature_archived))
+ return 0
+
+ temperature += self_temperature_delta
+
+ return 1
+ //Logic integrated from: temperature_mimic(model, conduction_coefficient) for efficiency
+
+/datum/gas_mixture/proc/temperature_share(datum/gas_mixture/sharer, conduction_coefficient)
+ var/delta_temperature = (temperature_archived - sharer.temperature_archived)
+ if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
+ var/self_heat_capacity = heat_capacity_archived()
+ var/sharer_heat_capacity = sharer.heat_capacity_archived()
+ if(!group_multiplier)
+ message_admins("Error! The gas mixture (ref \ref[src]) has no group multiplier!")
+ return
+
+ if((sharer_heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY))
+ var/heat = conduction_coefficient*delta_temperature* \
+ (self_heat_capacity*sharer_heat_capacity/(self_heat_capacity+sharer_heat_capacity))
+
+ temperature -= heat/(self_heat_capacity*group_multiplier)
+ sharer.temperature += heat/(sharer_heat_capacity*sharer.group_multiplier)
+
+/datum/gas_mixture/proc/temperature_mimic(turf/model, conduction_coefficient, border_multiplier)
+ var/delta_temperature = (temperature - model.temperature)
+ if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
+ var/self_heat_capacity = heat_capacity()//_archived()
+ if(!group_multiplier)
+ message_admins("Error! The gas mixture (ref \ref[src]) has no group multiplier!")
+ return
+
+ if((model.heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY))
+ var/heat = conduction_coefficient*delta_temperature* \
+ (self_heat_capacity*model.heat_capacity/(self_heat_capacity+model.heat_capacity))
+
+ if(border_multiplier)
+ temperature -= heat*border_multiplier/(self_heat_capacity*group_multiplier)
+ else
+ temperature -= heat/(self_heat_capacity*group_multiplier)
+
+/datum/gas_mixture/proc/temperature_turf_share(turf/simulated/sharer, conduction_coefficient)
+ var/delta_temperature = (temperature_archived - sharer.temperature)
+ if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
+ var/self_heat_capacity = heat_capacity()
+
+ if((sharer.heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY))
+ var/heat = conduction_coefficient*delta_temperature* \
+ (self_heat_capacity*sharer.heat_capacity/(self_heat_capacity+sharer.heat_capacity))
+
+ temperature -= heat/(self_heat_capacity*group_multiplier)
+ sharer.temperature += heat/sharer.heat_capacity
+
+/datum/gas_mixture/proc/compare(datum/gas_mixture/sample)
+ //Purpose: Compares sample to self to see if within acceptable ranges that group processing may be enabled
+ //Called by: Airgroups trying to rebuild
+ //Inputs: Gas mix to compare
+ //Outputs: 1 if can rebuild, 0 if not.
+ if(!sample) return 0
+
+ if((abs(oxygen-sample.oxygen) > MINIMUM_AIR_TO_SUSPEND) && \
+ ((oxygen < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.oxygen) || (oxygen > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.oxygen)))
+ return 0
+ if((abs(nitrogen-sample.nitrogen) > MINIMUM_AIR_TO_SUSPEND) && \
+ ((nitrogen < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.nitrogen) || (nitrogen > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.nitrogen)))
+ return 0
+ if((abs(carbon_dioxide-sample.carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && \
+ ((carbon_dioxide < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.carbon_dioxide) || (oxygen > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.carbon_dioxide)))
+ return 0
+ if((abs(toxins-sample.toxins) > MINIMUM_AIR_TO_SUSPEND) && \
+ ((toxins < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.toxins) || (toxins > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.toxins)))
+ return 0
+
+ if(total_moles() > MINIMUM_AIR_TO_SUSPEND)
+ if((abs(temperature-sample.temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) && \
+ ((temperature < (1-MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND)*sample.temperature) || (temperature > (1+MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND)*sample.temperature)))
+ //world << "temp fail [temperature] & [sample.temperature]"
+ return 0
+
+ if(sample.trace_gases.len)
+ for(var/datum/gas/trace_gas in sample.trace_gases)
+ if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND)
+ var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases
+ if(corresponding)
+ if((abs(trace_gas.moles - corresponding.moles) > MINIMUM_AIR_TO_SUSPEND) && \
+ ((corresponding.moles < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*trace_gas.moles) || (corresponding.moles > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*trace_gas.moles)))
+ return 0
+ else
+ return 0
+
+ if(trace_gases.len)
+ for(var/datum/gas/trace_gas in trace_gases)
+ if(trace_gas.moles > MINIMUM_AIR_TO_SUSPEND)
+ var/datum/gas/corresponding = locate(trace_gas.type) in sample.trace_gases
+ if(corresponding)
+ if((abs(trace_gas.moles - corresponding.moles) > MINIMUM_AIR_TO_SUSPEND) && \
+ ((trace_gas.moles < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*corresponding.moles) || (trace_gas.moles > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*corresponding.moles)))
+ return 0
+ else
+ return 0
+ return 1
+
+/datum/gas_mixture/proc/subtract(datum/gas_mixture/right_side)
+ //Purpose: Subtracts right_side from air_mixture. Used to help turfs mingle
+ //Called by: Pipelines ending in a break (or something)
+ //Inputs: Gas mix to remove
+ //Outputs: 1
+
+ oxygen -= right_side.oxygen
+ carbon_dioxide -= right_side.carbon_dioxide
+ nitrogen -= right_side.nitrogen
+ toxins -= right_side.toxins
+
+ if((trace_gases.len > 0)||(right_side.trace_gases.len > 0))
+ for(var/datum/gas/trace_gas in right_side.trace_gases)
+ var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases
+ if(!corresponding)
+ corresponding = new trace_gas.type()
+ trace_gases += corresponding
+
+ corresponding.moles -= trace_gas.moles
+ update_values()
+ return 1
\ No newline at end of file
diff --git a/code/ZAS/FEA_system.dm b/code/ZAS/FEA_system.dm
index 94b7c5cf6d..c2a33ad99d 100644
--- a/code/ZAS/FEA_system.dm
+++ b/code/ZAS/FEA_system.dm
@@ -64,49 +64,46 @@ atom/proc/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0)
return (!density || !height || air_group)
-turf
- CanPass(atom/movable/mover, turf/target, height=1.5,air_group=0)
- if(!target) return 0
+/turf/CanPass(atom/movable/mover, turf/target, height=1.5,air_group=0)
+ if(!target) return 0
- if(istype(mover)) // turf/Enter(...) will perform more advanced checks
- return !density
+ if(istype(mover)) // turf/Enter(...) will perform more advanced checks
+ return !density
- else // Now, doing more detailed checks for air movement and air group formation
- if(target.blocks_air||blocks_air)
+ else // Now, doing more detailed checks for air movement and air group formation
+ if(target.blocks_air||blocks_air)
+ return 0
+
+ for(var/obj/obstacle in src)
+ if(!obstacle.CanPass(mover, target, height, air_group))
return 0
-
- for(var/obj/obstacle in src)
- if(!obstacle.CanPass(mover, target, height, air_group))
+ if(target != src)
+ for(var/obj/obstacle in target)
+ if(!obstacle.CanPass(mover, src, height, air_group))
return 0
- if(target != src)
- for(var/obj/obstacle in target)
- if(!obstacle.CanPass(mover, src, height, air_group))
- return 0
- return 1
+ return 1
-var/global/datum/controller/air_system/air_master
+var/datum/controller/air_system/air_master
-datum
- controller
- air_system
- //Geoemetry lists
- var/list/turfs_with_connections = list()
- var/list/active_hotspots = list()
+/datum/controller/air_system/
+ //Geoemetry lists
+ var/list/turfs_with_connections = list()
+ var/list/active_hotspots = list()
- //Special functions lists
- var/list/tiles_to_reconsider_zones = list()
+ //Special functions lists
+ var/list/tiles_to_reconsider_zones = list()
- //Geometry updates lists
- var/list/tiles_to_update = list()
- var/list/connections_to_check = list()
+ //Geometry updates lists
+ var/list/tiles_to_update = list()
+ var/list/connections_to_check = list()
- var/current_cycle = 0
- var/update_delay = 5 //How long between check should it try to process atmos again.
- var/failed_ticks = 0 //How many ticks have runtimed?
+ var/current_cycle = 0
+ var/update_delay = 5 //How long between check should it try to process atmos again.
+ var/failed_ticks = 0 //How many ticks have runtimed?
- var/tick_progress = 0
+ var/tick_progress = 0
/* process()
@@ -122,97 +119,103 @@ datum
*/
- 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.
+/datum/controller/air_system/proc/setup()
+ //Purpose: Call this at the start to setup air groups geometry
+ // (Warning: Very processor intensive but only must be done once per round)
+ //Called by: Gameticker/Master controller
+ //Inputs: None.
+ //Outputs: None.
- set background = 1
- world << "\red \b Processing Geometry..."
- sleep(-1)
+ set background = 1
+ world << "\red \b Processing Geometry..."
+ sleep(-1)
- var/start_time = world.timeofday
+ var/start_time = world.timeofday
- var/simulated_turf_count = 0
+ var/simulated_turf_count = 0
- for(var/turf/simulated/S in world)
- simulated_turf_count++
- if(!S.zone && !S.blocks_air)
- if(S.CanPass(null, S, 0, 0))
- new/zone(S)
+ for(var/turf/simulated/S in world)
+ simulated_turf_count++
+ if(!S.zone && !S.blocks_air)
+ if(S.CanPass(null, S, 0, 0))
+ new/zone(S)
- for(var/turf/simulated/S in world)
- S.update_air_properties()
+ for(var/turf/simulated/S in world)
+ S.update_air_properties()
- world << {"Geometry initialized in [round(0.1*(world.timeofday-start_time),0.1)] seconds.
- Total Simulated Turfs: [simulated_turf_count]
- Total Zones: [zones.len]
- Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_count]"}
- /*
- spawn start()
+ world << {"Geometry initialized in [round(0.1*(world.timeofday-start_time),0.1)] seconds.
+Total Simulated Turfs: [simulated_turf_count]
+Total Zones: [zones.len]
+Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_count]"}
+ /*
+ spawn start()
- 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.
+/datum/controller/air_system/proc/start()
+ //Purpose: This is kicked off by the master controller, and controls the processing of all atmosphere.
+ //Called by: Master controller
+ //Inputs: None.
+ //Outputs: None.
- set background = 1
+ set background = 1
- while(1)
- if(!kill_air)
- current_cycle++
- var/success = tick() //Changed so that a runtime does not crash the ticker.
- if(!success) //Runtimed.
- failed_ticks++
- if(failed_ticks > 20)
- world << "ERROR IN ATMOS TICKER. Killing air simulation!"
- kill_air = 1
- sleep(max(5,update_delay*tick_multiplier))
- */
+ while(1)
+ if(!kill_air)
+ current_cycle++
+ var/success = tick() //Changed so that a runtime does not crash the ticker.
+ if(!success) //Runtimed.
+ failed_ticks++
+ if(failed_ticks > 20)
+ world << "ERROR IN ATMOS TICKER. Killing air simulation!"
+ kill_air = 1
+ sleep(max(5,update_delay*tick_multiplier))
+ */
- proc/tick()
- . = 1 //Set the default return value, for runtime detection.
+/datum/controller/air_system/proc/tick()
+ . = 1 //Set the default return value, for runtime detection.
- tick_progress = "update_air_properties"
- if(tiles_to_update.len) //If there are tiles to update, do so.
- for(var/turf/simulated/T in tiles_to_update)
- if(. && T && !T.update_air_properties())
- . = 0 //If a runtime occured, make sure we can sense it.
- //message_admins("ZASALERT: Unable run turf/simualted/update_air_properties()")
- tiles_to_update = list()
+ tick_progress = "update_air_properties"
+ if(tiles_to_update.len) //If there are tiles to update, do so.
+ for(var/turf/simulated/T in tiles_to_update)
+ if(. && T && !T.update_air_properties())
+ . = 0 //If a runtime occured, make sure we can sense it.
+ //message_admins("ZASALERT: Unable run turf/simualted/update_air_properties()")
+ if(.)
+ tiles_to_update = list()
- //Check sanity on connection objects.
- tick_progress = "connections_to_check"
- if(connections_to_check.len)
- for(var/connection/C in connections_to_check)
- C.CheckPassSanity()
- connections_to_check = list()
+ //Check sanity on connection objects.
+ if(.)
+ tick_progress = "connections_to_check"
+ if(connections_to_check.len)
+ for(var/connection/C in connections_to_check)
+ C.CheckPassSanity()
+ connections_to_check = list()
- //Ensure tiles still have zones.
- tick_progress = "tiles_to_reconsider_zones"
- if(tiles_to_reconsider_zones.len)
- for(var/turf/simulated/T in tiles_to_reconsider_zones)
- if(!T.zone)
- new /zone(T)
- tiles_to_reconsider_zones = list()
+ //Ensure tiles still have zones.
+ if(.)
+ tick_progress = "tiles_to_reconsider_zones"
+ if(tiles_to_reconsider_zones.len)
+ for(var/turf/simulated/T in tiles_to_reconsider_zones)
+ if(!T.zone)
+ new /zone(T)
+ tiles_to_reconsider_zones = list()
- //Process zones.
- tick_progress = "zone/process()"
- for(var/zone/Z in zones)
- if(Z.last_update < current_cycle)
- var/output = Z.process()
- if(Z)
- Z.last_update = current_cycle
- if(. && Z && !output)
- . = 0
- //Process fires.
- tick_progress = "active_hotspots (fire)"
- for(var/obj/fire/F in active_hotspots)
- if(. && F && !F.process())
- . = 0
+ //Process zones.
+ if(.)
+ tick_progress = "zone/process()"
+ for(var/zone/Z in zones)
+ if(Z.last_update < current_cycle)
+ var/output = Z.process()
+ if(Z)
+ Z.last_update = current_cycle
+ if(. && Z && !output)
+ . = 0
+ //Process fires.
+ if(.)
+ tick_progress = "active_hotspots (fire)"
+ for(var/obj/fire/F in active_hotspots)
+ if(. && F && !F.process())
+ . = 0
- tick_progress = "success"
\ No newline at end of file
+ if(.)
+ tick_progress = "success"
\ No newline at end of file
diff --git a/code/ZAS/Fire.dm b/code/ZAS/Fire.dm
index 023d60acf0..8973b3794b 100644
--- a/code/ZAS/Fire.dm
+++ b/code/ZAS/Fire.dm
@@ -30,7 +30,7 @@ turf/simulated/hotspot_expose(exposed_temperature, exposed_volume, soh)
var/igniting = 0
var/obj/effect/decal/cleanable/liquid_fuel/liquid = locate() in src
-
+
if(air_contents.check_combustability(liquid))
igniting = 1
@@ -43,132 +43,130 @@ turf/simulated/hotspot_expose(exposed_temperature, exposed_volume, soh)
return igniting
-obj
- fire
- //Icon for fire on turfs.
+/obj/fire
+ //Icon for fire on turfs.
- anchored = 1
- mouse_opacity = 0
+ anchored = 1
+ mouse_opacity = 0
- //luminosity = 3
+ //luminosity = 3
- icon = 'fire.dmi'
+ icon = 'fire.dmi'
+ icon_state = "1"
+
+ layer = TURF_LAYER
+
+ var/firelevel = 10000 //Calculated by gas_mixture.calculate_firelevel()
+
+/obj/fire/process()
+ . = 1
+
+ //get location and check if it is in a proper ZAS zone
+ var/turf/simulated/floor/S = loc
+ if(!S.zone)
+ del src
+
+ if(!istype(S))
+ del src
+
+ var/datum/gas_mixture/air_contents = S.return_air()
+ //get liquid fuels on the ground.
+ var/obj/effect/decal/cleanable/liquid_fuel/liquid = locate() in S
+ //and the volatile stuff from the air
+ var/datum/gas/volatile_fuel/fuel = locate() in air_contents.trace_gases
+
+ //since the air is processed in fractions, we need to make sure not to have any minuscle residue or
+ //the amount of moles might get to low for some functions to catch them and thus result in wonky behaviour
+ if(air_contents.oxygen < 0.001)
+ air_contents.oxygen = 0
+ if(air_contents.toxins < 0.001)
+ air_contents.toxins = 0
+ if(fuel)
+ if(fuel.moles < 0.001)
+ air_contents.trace_gases.Remove(fuel)
+
+ //check if there is something to combust
+ if(!air_contents.check_combustability(liquid))
+ del src
+
+ //get a firelevel and set the icon
+ firelevel = air_contents.calculate_firelevel(liquid)
+
+ if(firelevel > 6)
+ icon_state = "3"
+ SetLuminosity(7)
+ else if(firelevel > 2.5)
+ icon_state = "2"
+ SetLuminosity(5)
+ else
icon_state = "1"
+ SetLuminosity(3)
- layer = TURF_LAYER
+ //im not sure how to implement a version that works for every creature so for now monkeys are firesafe
+ for(var/mob/living/carbon/human/M in loc)
+ M.FireBurn(firelevel, air_contents.temperature, air_contents.return_pressure() ) //Burn the humans!
- var
- firelevel = 10000 //Calculated by gas_mixture.calculate_firelevel()
- process()
- . = 1
-
- //get location and check if it is in a proper ZAS zone
- var/turf/simulated/floor/S = loc
- if(!S.zone)
- del src
-
- if(!istype(S))
- del src
-
- var/datum/gas_mixture/air_contents = S.return_air()
- //get liquid fuels on the ground.
- var/obj/effect/decal/cleanable/liquid_fuel/liquid = locate() in S
- //and the volatile stuff from the air
- var/datum/gas/volatile_fuel/fuel = locate() in air_contents.trace_gases
-
- //since the air is processed in fractions, we need to make sure not to have any minuscle residue or
- //the amount of moles might get to low for some functions to catch them and thus result in wonky behaviour
- if(air_contents.oxygen < 0.001)
- air_contents.oxygen = 0
- if(air_contents.toxins < 0.001)
- air_contents.toxins = 0
- if(fuel)
- if(fuel.moles < 0.001)
- air_contents.trace_gases.Remove(fuel)
-
- //check if there is something to combust
- if(!air_contents.check_combustability(liquid))
- del src
-
- //get a firelevel and set the icon
- firelevel = air_contents.calculate_firelevel(liquid)
-
- if(firelevel > 6)
- icon_state = "3"
- SetLuminosity(7)
- else if(firelevel > 2.5)
- icon_state = "2"
- SetLuminosity(5)
- else
- icon_state = "1"
- SetLuminosity(3)
-
- //im not sure how to implement a version that works for every creature so for now monkeys are firesafe
- for(var/mob/living/carbon/human/M in loc)
- M.FireBurn(firelevel, air_contents.temperature, air_contents.return_pressure() ) //Burn the humans!
+ //spread!
+ for(var/direction in cardinal)
+ if(S.air_check_directions&direction) //Grab all valid bordering tiles
-
- //spread!
- for(var/direction in cardinal)
- if(S.air_check_directions&direction) //Grab all valid bordering tiles
+ var/turf/simulated/enemy_tile = get_step(S, direction)
- var/turf/simulated/enemy_tile = get_step(S, direction)
+ if(istype(enemy_tile))
+ //If extinguisher mist passed over the turf it's trying to spread to, don't spread and
+ //reduce firelevel.
+ if(enemy_tile.fire_protection > world.time-30)
+ firelevel -= 1.5
+ continue
- if(istype(enemy_tile))
- //If extinguisher mist passed over the turf it's trying to spread to, don't spread and
- //reduce firelevel.
- if(enemy_tile.fire_protection > world.time-30)
- firelevel -= 1.5
- continue
+ //Spread the fire.
+ if(!(locate(/obj/fire) in enemy_tile))
+ if( prob( 50 + 50 * (firelevel/vsc.fire_firelevel_multiplier) ) && S.CanPass(null, enemy_tile, 0,0) && enemy_tile.CanPass(null, S, 0,0))
+ new/obj/fire(enemy_tile,firelevel)
+
+ //seperate part of the present gas
+ //this is done to prevent the fire burning all gases in a single pass
+ var/datum/gas_mixture/flow = air_contents.remove_ratio(vsc.fire_consuption_rate)
- //Spread the fire.
- if(!(locate(/obj/fire) in enemy_tile))
- if( prob( 50 + 50 * (firelevel/vsc.fire_firelevel_multiplier) ) && S.CanPass(null, enemy_tile, 0,0) && enemy_tile.CanPass(null, S, 0,0))
- new/obj/fire(enemy_tile,firelevel)
-
- //seperate part of the present gas
- //this is done to prevent the fire burning all gases in a single pass
- var/datum/gas_mixture/flow = air_contents.remove_ratio(vsc.fire_consuption_rate)
-
///////////////////////////////// FLOW HAS BEEN CREATED /// DONT DELETE THE FIRE UNTIL IT IS MERGED BACK OR YOU WILL DELETE AIR ///////////////////////////////////////////////
-
- if(flow)
- if(flow.check_combustability(liquid))
- //Ensure flow temperature is higher than minimum fire temperatures.
- //this creates some energy ex nihilo but is necessary to get a fire started
- //lets just pretend this energy comes from the ignition source and dont mention this again
- //flow.temperature = max(PLASMA_MINIMUM_BURN_TEMPERATURE+0.1,flow.temperature)
-
- //burn baby burn!
- flow.zburn(liquid,1)
-
- //merge the air back
- S.assume_air(flow)
+
+ if(flow)
+ if(flow.check_combustability(liquid))
+ //Ensure flow temperature is higher than minimum fire temperatures.
+ //this creates some energy ex nihilo but is necessary to get a fire started
+ //lets just pretend this energy comes from the ignition source and dont mention this again
+ //flow.temperature = max(PLASMA_MINIMUM_BURN_TEMPERATURE+0.1,flow.temperature)
+
+ //burn baby burn!
+ flow.zburn(liquid,1)
+
+ //merge the air back
+ S.assume_air(flow)
///////////////////////////////// FLOW HAS BEEN REMERGED /// feel free to delete the fire again from here on //////////////////////////////////////////////////////////////////
-
- New(newLoc,fl)
- ..()
- if(!istype(loc, /turf))
- del src
+/obj/fire/New(newLoc,fl)
+ ..()
- dir = pick(cardinal)
- SetLuminosity(3)
- firelevel = fl
- air_master.active_hotspots.Add(src)
+ if(!istype(loc, /turf))
+ del src
+
+ dir = pick(cardinal)
+ SetLuminosity(3)
+ firelevel = fl
+ air_master.active_hotspots.Add(src)
- Del()
- if (istype(loc, /turf/simulated))
- SetLuminosity(0)
+/obj/fire/Del()
+ if (istype(loc, /turf/simulated))
+ SetLuminosity(0)
- loc = null
- air_master.active_hotspots.Remove(src)
+ loc = null
+ air_master.active_hotspots.Remove(src)
- ..()
+ ..()
@@ -180,13 +178,13 @@ turf/simulated/apply_fire_protection()
datum/gas_mixture/proc/zburn(obj/effect/decal/cleanable/liquid_fuel/liquid,force_burn)
var/value = 0
-
+
if((temperature > PLASMA_MINIMUM_BURN_TEMPERATURE || force_burn) && check_combustability(liquid) )
- var/total_fuel = 0
+ var/total_fuel = 0
var/datum/gas/volatile_fuel/fuel = locate() in trace_gases
total_fuel += toxins
-
+
if(fuel)
//Volatile Fuel
total_fuel += fuel.moles
@@ -207,7 +205,7 @@ datum/gas_mixture/proc/zburn(obj/effect/decal/cleanable/liquid_fuel/liquid,force
//determine the amount of oxygen used
var/total_oxygen = min(oxygen, 2 * total_fuel)
-
+
//determine the amount of fuel actually used
var/used_fuel_ratio = min(oxygen / 2 , total_fuel) / total_fuel
total_fuel = total_fuel * used_fuel_ratio
@@ -234,31 +232,31 @@ datum/gas_mixture/proc/zburn(obj/effect/decal/cleanable/liquid_fuel/liquid,force
//calculate the energy produced by the reaction and then set the new temperature of the mix
temperature = (starting_energy + vsc.fire_fuel_energy_release * total_fuel) / heat_capacity()
-
+
update_values()
value = total_reactants * used_reactants_ratio
return value
datum/gas_mixture/proc/check_combustability(obj/effect/decal/cleanable/liquid_fuel/liquid)
//this check comes up very often and is thus centralized here to ease adding stuff
-
- var/datum/gas/volatile_fuel/fuel = locate() in trace_gases
+
+ var/datum/gas/volatile_fuel/fuel = locate() in trace_gases
var/value = 0
-
+
if(oxygen && (toxins || fuel || liquid))
value = 1
-
+
return value
datum/gas_mixture/proc/calculate_firelevel(obj/effect/decal/cleanable/liquid_fuel/liquid)
//Calculates the firelevel based on one equation instead of having to do this multiple times in different areas.
-
+
var/datum/gas/volatile_fuel/fuel = locate() in trace_gases
var/total_fuel = 0
var/firelevel = 0
-
+
if(check_combustability(liquid))
-
+
total_fuel += toxins
if(liquid)
@@ -268,16 +266,16 @@ datum/gas_mixture/proc/calculate_firelevel(obj/effect/decal/cleanable/liquid_fue
total_fuel += fuel.moles
var/total_combustables = (total_fuel + oxygen)
-
+
if(total_fuel > 0 && oxygen > 0)
-
+
//slows down the burning when the concentration of the reactants is low
var/dampening_multiplier = total_combustables / (total_combustables + nitrogen + carbon_dioxide)
//calculates how close the mixture of the reactants is to the optimum
var/mix_multiplier = 1 / (1 + (5 * ((oxygen / total_combustables) ^2)))
//toss everything together
firelevel = vsc.fire_firelevel_multiplier * mix_multiplier * dampening_multiplier
-
+
return max( 0, firelevel)
diff --git a/code/ZAS/Plasma.dm b/code/ZAS/Plasma.dm
index 3196d93db9..9f0e95f661 100644
--- a/code/ZAS/Plasma.dm
+++ b/code/ZAS/Plasma.dm
@@ -1,61 +1,61 @@
var/image/contamination_overlay = image('icons/effects/contamination.dmi')
-pl_control/var
- PLASMA_DMG = 3
- PLASMA_DMG_NAME = "Plasma Damage Amount"
- PLASMA_DMG_DESC = "Self Descriptive"
+/pl_control
+ var/PLASMA_DMG = 3
+ var/PLASMA_DMG_NAME = "Plasma Damage Amount"
+ var/PLASMA_DMG_DESC = "Self Descriptive"
- CLOTH_CONTAMINATION = 1
- CLOTH_CONTAMINATION_NAME = "Cloth Contamination"
- CLOTH_CONTAMINATION_DESC = "If this is on, plasma does damage by getting into cloth."
+ var/CLOTH_CONTAMINATION = 1
+ var/CLOTH_CONTAMINATION_NAME = "Cloth Contamination"
+ var/CLOTH_CONTAMINATION_DESC = "If this is on, plasma does damage by getting into cloth."
- PLASMAGUARD_ONLY = 0
- PLASMAGUARD_ONLY_NAME = "\"PlasmaGuard Only\""
- PLASMAGUARD_ONLY_DESC = "If this is on, only biosuits and spacesuits protect against contamination and ill effects."
+ var/PLASMAGUARD_ONLY = 0
+ var/PLASMAGUARD_ONLY_NAME = "\"PlasmaGuard Only\""
+ var/PLASMAGUARD_ONLY_DESC = "If this is on, only biosuits and spacesuits protect against contamination and ill effects."
- GENETIC_CORRUPTION = 0
- GENETIC_CORRUPTION_NAME = "Genetic Corruption Chance"
- GENETIC_CORRUPTION_DESC = "Chance of genetic corruption as well as toxic damage, X in 10,000."
+ var/GENETIC_CORRUPTION = 0
+ var/GENETIC_CORRUPTION_NAME = "Genetic Corruption Chance"
+ var/GENETIC_CORRUPTION_DESC = "Chance of genetic corruption as well as toxic damage, X in 10,000."
- SKIN_BURNS = 0
- SKIN_BURNS_DESC = "Plasma has an effect similar to mustard gas on the un-suited."
- SKIN_BURNS_NAME = "Skin Burns"
+ var/SKIN_BURNS = 0
+ var/SKIN_BURNS_DESC = "Plasma has an effect similar to mustard gas on the un-suited."
+ var/SKIN_BURNS_NAME = "Skin Burns"
- EYE_BURNS = 1
- EYE_BURNS_NAME = "Eye Burns"
- EYE_BURNS_DESC = "Plasma burns the eyes of anyone not wearing eye protection."
+ var/EYE_BURNS = 1
+ var/EYE_BURNS_NAME = "Eye Burns"
+ var/EYE_BURNS_DESC = "Plasma burns the eyes of anyone not wearing eye protection."
- CONTAMINATION_LOSS = 0.02
- CONTAMINATION_LOSS_NAME = "Contamination Loss"
- CONTAMINATION_LOSS_DESC = "How much toxin damage is dealt from contaminated clothing" //Per tick? ASK ARYN
+ var/CONTAMINATION_LOSS = 0.02
+ var/CONTAMINATION_LOSS_NAME = "Contamination Loss"
+ var/CONTAMINATION_LOSS_DESC = "How much toxin damage is dealt from contaminated clothing" //Per tick? ASK ARYN
- PLASMA_HALLUCINATION = 0
- PLASMA_HALLUCINATION_NAME = "Plasma Hallucination"
- PLASMA_HALLUCINATION_DESC = "Does being in plasma cause you to hallucinate?"
+ var/PLASMA_HALLUCINATION = 0
+ var/PLASMA_HALLUCINATION_NAME = "Plasma Hallucination"
+ var/PLASMA_HALLUCINATION_DESC = "Does being in plasma cause you to hallucinate?"
- N2O_HALLUCINATION = 1
- N2O_HALLUCINATION_NAME = "N2O Hallucination"
- N2O_HALLUCINATION_DESC = "Does being in sleeping gas cause you to hallucinate?"
+ var/N2O_HALLUCINATION = 1
+ var/N2O_HALLUCINATION_NAME = "N2O Hallucination"
+ var/N2O_HALLUCINATION_DESC = "Does being in sleeping gas cause you to hallucinate?"
obj/var/contaminated = 0
-obj/item/proc
- can_contaminate()
- //Clothing and backpacks can be contaminated.
- if(flags & PLASMAGUARD) return 0
- else if(istype(src,/obj/item/weapon/storage/backpack)) return 0 //Cannot be washed :(
- else if(istype(src,/obj/item/clothing)) return 1
- contaminate()
- //Do a contamination overlay? Temporary measure to keep contamination less deadly than it was.
- if(!contaminated)
- contaminated = 1
- overlays += contamination_overlay
+/obj/item/proc/can_contaminate()
+ //Clothing and backpacks can be contaminated.
+ if(flags & PLASMAGUARD) return 0
+ else if(istype(src,/obj/item/weapon/storage/backpack)) return 0 //Cannot be washed :(
+ else if(istype(src,/obj/item/clothing)) return 1
- decontaminate()
- contaminated = 0
- overlays -= contamination_overlay
+/obj/item/proc/contaminate()
+ //Do a contamination overlay? Temporary measure to keep contamination less deadly than it was.
+ if(!contaminated)
+ contaminated = 1
+ overlays += contamination_overlay
+
+/obj/item/proc/decontaminate()
+ contaminated = 0
+ overlays -= contamination_overlay
/mob/proc/contaminate()
diff --git a/code/ZAS/Variable Settings.dm b/code/ZAS/Variable Settings.dm
index dd22765e99..80e243e3c5 100644
--- a/code/ZAS/Variable Settings.dm
+++ b/code/ZAS/Variable Settings.dm
@@ -1,322 +1,332 @@
var/global/vs_control/vsc = new
-vs_control/var
- fire_consuption_rate = 0.25
- fire_consuption_rate_NAME = "Fire - Air Consumption Ratio"
- fire_consuption_rate_DESC = "Ratio of air removed and combusted per tick."
+/vs_control
+ var/fire_consuption_rate = 0.25
+ var/fire_consuption_rate_NAME = "Fire - Air Consumption Ratio"
+ var/fire_consuption_rate_DESC = "Ratio of air removed and combusted per tick."
- fire_firelevel_multiplier = 25
- fire_firelevel_multiplier_NAME = "Fire - Firelevel Constant"
- fire_firelevel_multiplier_DESC = "Multiplied by the equation for firelevel, affects mainly the extingiushing of fires."
+ var/fire_firelevel_multiplier = 25
+ var/fire_firelevel_multiplier_NAME = "Fire - Firelevel Constant"
+ var/fire_firelevel_multiplier_DESC = "Multiplied by the equation for firelevel, affects mainly the extingiushing of fires."
- fire_fuel_energy_release = 397000
- fire_fuel_energy_release_NAME = "Fire - Fuel energy release"
- fire_fuel_energy_release_DESC = "The energy in joule released when burning one mol of a burnable substance"
-
-
- airflow_lightest_pressure = 20
- airflow_lightest_pressure_NAME = "Airflow - Small Movement Threshold %"
- airflow_lightest_pressure_DESC = "Percent of 1 Atm. at which items with the small weight classes will move."
-
- airflow_light_pressure = 35
- airflow_light_pressure_NAME = "Airflow - Medium Movement Threshold %"
- airflow_light_pressure_DESC = "Percent of 1 Atm. at which items with the medium weight classes will move."
-
- airflow_medium_pressure = 50
- airflow_medium_pressure_NAME = "Airflow - Heavy Movement Threshold %"
- airflow_medium_pressure_DESC = "Percent of 1 Atm. at which items with the largest weight classes will move."
-
- airflow_heavy_pressure = 65
- airflow_heavy_pressure_NAME = "Airflow - Mob Movement Threshold %"
- airflow_heavy_pressure_DESC = "Percent of 1 Atm. at which mobs will move."
-
- airflow_dense_pressure = 85
- airflow_dense_pressure_NAME = "Airflow - Dense Movement Threshold %"
- airflow_dense_pressure_DESC = "Percent of 1 Atm. at which items with canisters and closets will move."
-
- airflow_stun_pressure = 60
- airflow_stun_pressure_NAME = "Airflow - Mob Stunning Threshold %"
- airflow_stun_pressure_DESC = "Percent of 1 Atm. at which mobs will be stunned by airflow."
-
- airflow_stun_cooldown = 60
- airflow_stun_cooldown_NAME = "Aiflow Stunning - Cooldown"
- airflow_stun_cooldown_DESC = "How long, in tenths of a second, to wait before stunning them again."
-
- airflow_stun = 1
- airflow_stun_NAME = "Airflow Impact - Stunning"
- airflow_stun_DESC = "How much a mob is stunned when hit by an object."
-
- airflow_damage = 2
- airflow_damage_NAME = "Airflow Impact - Damage"
- airflow_damage_DESC = "Damage from airflow impacts."
-
- airflow_speed_decay = 1.5
- airflow_speed_decay_NAME = "Airflow Speed Decay"
- airflow_speed_decay_DESC = "How rapidly the speed gained from airflow decays."
-
- airflow_delay = 30
- airflow_delay_NAME = "Airflow Retrigger Delay"
- airflow_delay_DESC = "Time in deciseconds before things can be moved by airflow again."
-
- airflow_mob_slowdown = 1
- airflow_mob_slowdown_NAME = "Airflow Slowdown"
- airflow_mob_slowdown_DESC = "Time in tenths of a second to add as a delay to each movement by a mob if they are fighting the pull of the airflow."
+ var/fire_fuel_energy_release = 397000
+ var/fire_fuel_energy_release_NAME = "Fire - Fuel energy release"
+ var/fire_fuel_energy_release_DESC = "The energy in joule released when burning one mol of a burnable substance"
-vs_control
- var
- list/settings = list()
- list/bitflags = list("1","2","4","8","16","32","64","128","256","512","1024")
- pl_control/plc = new()
+ var/airflow_lightest_pressure = 20
+ var/airflow_lightest_pressure_NAME = "Airflow - Small Movement Threshold %"
+ var/airflow_lightest_pressure_DESC = "Percent of 1 Atm. at which items with the small weight classes will move."
- New()
- . = ..()
- settings = vars.Copy()
+ var/airflow_light_pressure = 35
+ var/airflow_light_pressure_NAME = "Airflow - Medium Movement Threshold %"
+ var/airflow_light_pressure_DESC = "Percent of 1 Atm. at which items with the medium weight classes will move."
- 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)
+ var/airflow_medium_pressure = 50
+ var/airflow_medium_pressure_NAME = "Airflow - Heavy Movement Threshold %"
+ var/airflow_medium_pressure_DESC = "Percent of 1 Atm. at which items with the largest weight classes will move."
+
+ var/airflow_heavy_pressure = 65
+ var/airflow_heavy_pressure_NAME = "Airflow - Mob Movement Threshold %"
+ var/airflow_heavy_pressure_DESC = "Percent of 1 Atm. at which mobs will move."
+
+ var/airflow_dense_pressure = 85
+ var/airflow_dense_pressure_NAME = "Airflow - Dense Movement Threshold %"
+ var/airflow_dense_pressure_DESC = "Percent of 1 Atm. at which items with canisters and closets will move."
+
+ var/airflow_stun_pressure = 60
+ var/airflow_stun_pressure_NAME = "Airflow - Mob Stunning Threshold %"
+ var/airflow_stun_pressure_DESC = "Percent of 1 Atm. at which mobs will be stunned by airflow."
+
+ var/airflow_stun_cooldown = 60
+ var/airflow_stun_cooldown_NAME = "Aiflow Stunning - Cooldown"
+ var/airflow_stun_cooldown_DESC = "How long, in tenths of a second, to wait before stunning them again."
+
+ var/airflow_stun = 1
+ var/airflow_stun_NAME = "Airflow Impact - Stunning"
+ var/airflow_stun_DESC = "How much a mob is stunned when hit by an object."
+
+ var/airflow_damage = 2
+ var/airflow_damage_NAME = "Airflow Impact - Damage"
+ var/airflow_damage_DESC = "Damage from airflow impacts."
+
+ var/airflow_speed_decay = 1.5
+ var/airflow_speed_decay_NAME = "Airflow Speed Decay"
+ var/airflow_speed_decay_DESC = "How rapidly the speed gained from airflow decays."
+
+ var/airflow_delay = 30
+ var/airflow_delay_NAME = "Airflow Retrigger Delay"
+ var/airflow_delay_DESC = "Time in deciseconds before things can be moved by airflow again."
+
+ var/airflow_mob_slowdown = 1
+ var/airflow_mob_slowdown_NAME = "Airflow Slowdown"
+ var/airflow_mob_slowdown_DESC = "Time in tenths of a second to add as a delay to each movement by a mob if they are fighting the pull of the airflow."
+
+ var/connection_insulation = 0.4
+ var/connection_insulation_NAME = "Connections - Insulation"
+ var/connection_insulation_DESC = "How insulative a connection is, in terms of heat transfer. 1 is perfectly insulative, and 0 is perfectly conductive."
+
+ var/connection_temperature_delta = 10
+ var/connection_temperature_delta_NAME = "Connections - Temperature Difference"
+ var/connection_temperature_delta_DESC = "The smallest temperature difference which will cause heat to travel through doors."
+
+
+/vs_control/var/list/settings = list()
+/vs_control/var/list/bitflags = list("1","2","4","8","16","32","64","128","256","512","1024")
+/vs_control/var/pl_control/plc = new()
+
+/vs_control/New()
+ . = ..()
+ settings = vars.Copy()
+
+ var/datum/D = new() //Ensure only unique vars are put through by making a datum and removing all common vars.
+ for(var/V in D.vars)
+ settings -= V
+
+ for(var/V in settings)
+ if(findtextEx(V,"_RANDOM") || findtextEx(V,"_DESC") || findtextEx(V,"_METHOD"))
settings -= V
- for(var/V in settings)
- if(findtextEx(V,"_RANDOM") || findtextEx(V,"_DESC") || findtextEx(V,"_METHOD"))
- settings -= V
+ settings -= "settings"
+ settings -= "bitflags"
+ settings -= "plc"
- settings -= "settings"
- settings -= "bitflags"
- settings -= "plc"
-
- proc/ChangeSettingsDialog(mob/user,list/L)
- //var/which = input(user,"Choose a setting:") in L
- var/dat = ""
- for(var/ch in L)
- if(findtextEx(ch,"_RANDOM") || findtextEx(ch,"_DESC") || findtextEx(ch,"_METHOD") || findtextEx(ch,"_NAME")) continue
- var/vw
- var/vw_desc = "No Description."
- var/vw_name = ch
- if(ch in plc.settings)
- vw = plc.vars[ch]
- if("[ch]_DESC" in plc.vars) vw_desc = plc.vars["[ch]_DESC"]
- if("[ch]_NAME" in plc.vars) vw_name = plc.vars["[ch]_NAME"]
- else
- vw = vars[ch]
- if("[ch]_DESC" in vars) vw_desc = vars["[ch]_DESC"]
- if("[ch]_NAME" in vars) vw_name = vars["[ch]_NAME"]
- dat += "[vw_name] = [vw] \[Change\]
"
- dat += "[vw_desc]
"
- user << browse(dat,"window=settings")
- Topic(href,href_list)
- if("changevar" in href_list)
- ChangeSetting(usr,href_list["changevar"])
- proc/ChangeSetting(mob/user,ch)
+/vs_control/proc/ChangeSettingsDialog(mob/user,list/L)
+ //var/which = input(user,"Choose a setting:") in L
+ var/dat = ""
+ for(var/ch in L)
+ if(findtextEx(ch,"_RANDOM") || findtextEx(ch,"_DESC") || findtextEx(ch,"_METHOD") || findtextEx(ch,"_NAME")) continue
var/vw
- var/how = "Text"
- var/display_description = ch
+ var/vw_desc = "No Description."
+ var/vw_name = ch
if(ch in plc.settings)
vw = plc.vars[ch]
- if("[ch]_NAME" in plc.vars)
- display_description = plc.vars["[ch]_NAME"]
- if("[ch]_METHOD" in plc.vars)
- how = plc.vars["[ch]_METHOD"]
- else
- if(isnum(vw))
- how = "Numeric"
- else
- how = "Text"
+ if("[ch]_DESC" in plc.vars) vw_desc = plc.vars["[ch]_DESC"]
+ if("[ch]_NAME" in plc.vars) vw_name = plc.vars["[ch]_NAME"]
else
vw = vars[ch]
- if("[ch]_NAME" in vars)
- display_description = vars["[ch]_NAME"]
- if("[ch]_METHOD" in vars)
- how = vars["[ch]_METHOD"]
+ if("[ch]_DESC" in vars) vw_desc = vars["[ch]_DESC"]
+ if("[ch]_NAME" in vars) vw_name = vars["[ch]_NAME"]
+ dat += "[vw_name] = [vw] \[Change\]
"
+ dat += "[vw_desc]
"
+ user << browse(dat,"window=settings")
+
+/vs_control/Topic(href,href_list)
+ if("changevar" in href_list)
+ ChangeSetting(usr,href_list["changevar"])
+
+/vs_control/proc/ChangeSetting(mob/user,ch)
+ var/vw
+ var/how = "Text"
+ var/display_description = ch
+ if(ch in plc.settings)
+ vw = plc.vars[ch]
+ if("[ch]_NAME" in plc.vars)
+ display_description = plc.vars["[ch]_NAME"]
+ if("[ch]_METHOD" in plc.vars)
+ how = plc.vars["[ch]_METHOD"]
+ else
+ if(isnum(vw))
+ how = "Numeric"
else
- if(isnum(vw))
- how = "Numeric"
- else
- how = "Text"
- var/newvar = vw
- switch(how)
- if("Numeric")
- newvar = input(user,"Enter a number:","Settings",newvar) as num
- if("Bit Flag")
- var/flag = input(user,"Toggle which bit?","Settings") in bitflags
- flag = text2num(flag)
- if(newvar & flag)
- newvar &= ~flag
- else
- newvar |= flag
- if("Toggle")
- newvar = !newvar
- if("Text")
- newvar = input(user,"Enter a string:","Settings",newvar) as text
- if("Long Text")
- newvar = input(user,"Enter text:","Settings",newvar) as message
- vw = newvar
- if(ch in plc.settings)
- plc.vars[ch] = vw
+ how = "Text"
+ else
+ vw = vars[ch]
+ if("[ch]_NAME" in vars)
+ display_description = vars["[ch]_NAME"]
+ if("[ch]_METHOD" in vars)
+ how = vars["[ch]_METHOD"]
else
- vars[ch] = vw
- if(how == "Toggle")
- newvar = (newvar?"ON":"OFF")
- world << "\blue [key_name(user)] changed the setting [display_description] to [newvar]."
- if(ch in plc.settings)
- ChangeSettingsDialog(user,plc.settings)
- else
- ChangeSettingsDialog(user,settings)
- proc/RandomizeWithProbability()
- for(var/V in settings)
- var/newvalue
- if("[V]_RANDOM" in vars)
- if(isnum(vars["[V]_RANDOM"]))
- newvalue = prob(vars["[V]_RANDOM"])
- else if(istext(vars["[V]_RANDOM"]))
- newvalue = roll(vars["[V]_RANDOM"])
- else
- newvalue = vars[V]
- V = newvalue
+ if(isnum(vw))
+ how = "Numeric"
+ else
+ how = "Text"
+ var/newvar = vw
+ switch(how)
+ if("Numeric")
+ newvar = input(user,"Enter a number:","Settings",newvar) as num
+ if("Bit Flag")
+ var/flag = input(user,"Toggle which bit?","Settings") in bitflags
+ flag = text2num(flag)
+ if(newvar & flag)
+ newvar &= ~flag
+ else
+ newvar |= flag
+ if("Toggle")
+ newvar = !newvar
+ if("Text")
+ newvar = input(user,"Enter a string:","Settings",newvar) as text
+ if("Long Text")
+ newvar = input(user,"Enter text:","Settings",newvar) as message
+ vw = newvar
+ if(ch in plc.settings)
+ plc.vars[ch] = vw
+ else
+ vars[ch] = vw
+ if(how == "Toggle")
+ newvar = (newvar?"ON":"OFF")
+ world << "\blue [key_name(user)] changed the setting [display_description] to [newvar]."
+ if(ch in plc.settings)
+ ChangeSettingsDialog(user,plc.settings)
+ else
+ ChangeSettingsDialog(user,settings)
- proc/ChangePlasma()
- for(var/V in plc.settings)
- plc.Randomize(V)
-
- proc/SetDefault(var/mob/user)
- var/list/setting_choices = list("Plasma - Standard", "Plasma - Low Hazard", "Plasma - High Hazard", "Plasma - Oh Shit!",\
- "ZAS - Normal", "ZAS - Forgiving", "ZAS - Dangerous", "ZAS - Hellish")
- var/def = input(user, "Which of these presets should be used?") as null|anything in setting_choices
- if(!def)
- return
- switch(def)
- if("Plasma - Standard")
- plc.CLOTH_CONTAMINATION = 1 //If this is on, plasma does damage by getting into cloth.
- plc.PLASMAGUARD_ONLY = 0
- plc.GENETIC_CORRUPTION = 0 //Chance of genetic corruption as well as toxic damage, X in 1000.
- plc.SKIN_BURNS = 0 //Plasma has an effect similar to mustard gas on the un-suited.
- plc.EYE_BURNS = 1 //Plasma burns the eyes of anyone not wearing eye protection.
- plc.PLASMA_HALLUCINATION = 0
- plc.CONTAMINATION_LOSS = 0.02
-
- if("Plasma - Low Hazard")
- plc.CLOTH_CONTAMINATION = 0 //If this is on, plasma does damage by getting into cloth.
- plc.PLASMAGUARD_ONLY = 0
- plc.GENETIC_CORRUPTION = 0 //Chance of genetic corruption as well as toxic damage, X in 1000
- plc.SKIN_BURNS = 0 //Plasma has an effect similar to mustard gas on the un-suited.
- plc.EYE_BURNS = 1 //Plasma burns the eyes of anyone not wearing eye protection.
- plc.PLASMA_HALLUCINATION = 0
- plc.CONTAMINATION_LOSS = 0.01
-
- if("Plasma - High Hazard")
- plc.CLOTH_CONTAMINATION = 1 //If this is on, plasma does damage by getting into cloth.
- plc.PLASMAGUARD_ONLY = 0
- plc.GENETIC_CORRUPTION = 0 //Chance of genetic corruption as well as toxic damage, X in 1000.
- plc.SKIN_BURNS = 1 //Plasma has an effect similar to mustard gas on the un-suited.
- plc.EYE_BURNS = 1 //Plasma burns the eyes of anyone not wearing eye protection.
- plc.PLASMA_HALLUCINATION = 1
- plc.CONTAMINATION_LOSS = 0.05
-
- if("Plasma - Oh Shit!")
- plc.CLOTH_CONTAMINATION = 1 //If this is on, plasma does damage by getting into cloth.
- plc.PLASMAGUARD_ONLY = 1
- plc.GENETIC_CORRUPTION = 5 //Chance of genetic corruption as well as toxic damage, X in 1000.
- plc.SKIN_BURNS = 1 //Plasma has an effect similar to mustard gas on the un-suited.
- plc.EYE_BURNS = 1 //Plasma burns the eyes of anyone not wearing eye protection.
- plc.PLASMA_HALLUCINATION = 1
- plc.CONTAMINATION_LOSS = 0.075
-
- if("ZAS - Normal")
- airflow_lightest_pressure = 20
- airflow_light_pressure = 35
- airflow_medium_pressure = 50
- airflow_heavy_pressure = 65
- airflow_dense_pressure = 85
- airflow_stun_pressure = 60
- airflow_stun_cooldown = 60
- airflow_stun = 1
- airflow_damage = 2
- airflow_speed_decay = 1.5
- airflow_delay = 30
- airflow_mob_slowdown = 1
-
- if("ZAS - Forgiving")
- airflow_lightest_pressure = 45
- airflow_light_pressure = 60
- airflow_medium_pressure = 120
- airflow_heavy_pressure = 110
- airflow_dense_pressure = 200
- airflow_stun_pressure = 150
- airflow_stun_cooldown = 90
- airflow_stun = 0.15
- airflow_damage = 0.15
- airflow_speed_decay = 1.5
- airflow_delay = 50
- airflow_mob_slowdown = 0
-
- if("ZAS - Dangerous")
- airflow_lightest_pressure = 15
- airflow_light_pressure = 30
- airflow_medium_pressure = 45
- airflow_heavy_pressure = 55
- airflow_dense_pressure = 70
- airflow_stun_pressure = 50
- airflow_stun_cooldown = 50
- airflow_stun = 2
- airflow_damage = 3
- airflow_speed_decay = 1.2
- airflow_delay = 25
- airflow_mob_slowdown = 2
-
- if("ZAS - Hellish")
- airflow_lightest_pressure = 20
- airflow_light_pressure = 30
- airflow_medium_pressure = 40
- airflow_heavy_pressure = 50
- airflow_dense_pressure = 60
- airflow_stun_pressure = 40
- airflow_stun_cooldown = 40
- airflow_stun = 3
- airflow_damage = 4
- airflow_speed_decay = 1
- airflow_delay = 20
- airflow_mob_slowdown = 3
-
-
- world << "\blue [key_name(user)] changed the global plasma/ZAS settings to \"[def]\""
-
-pl_control
- var/list/settings = list()
- New()
- . = ..()
- settings = vars.Copy()
-
- var/datum/D = new() //Ensure only unique vars are put through by making a datum and removing all common vars.
- for(var/V in D.vars)
- settings -= V
-
- for(var/V in settings)
- if(findtextEx(V,"_RANDOM") || findtextEx(V,"_DESC"))
- settings -= V
-
- settings -= "settings"
- proc/Randomize(V)
+/vs_control/proc/RandomizeWithProbability()
+ for(var/V in settings)
var/newvalue
if("[V]_RANDOM" in vars)
if(isnum(vars["[V]_RANDOM"]))
newvalue = prob(vars["[V]_RANDOM"])
else if(istext(vars["[V]_RANDOM"]))
- var/txt = vars["[V]_RANDOM"]
- if(findtextEx(txt,"PROB"))
- txt = text2list(txt,"/")
- txt[1] = replacetext(txt[1],"PROB","")
- var/p = text2num(txt[1])
- var/r = txt[2]
- if(prob(p))
- newvalue = roll(r)
- else
- newvalue = vars[V]
- else if(findtextEx(txt,"PICK"))
- txt = replacetext(txt,"PICK","")
- txt = text2list(txt,",")
- newvalue = pick(txt)
- else
- newvalue = roll(txt)
+ newvalue = roll(vars["[V]_RANDOM"])
else
newvalue = vars[V]
- vars[V] = newvalue
+ V = newvalue
+
+/vs_control/proc/ChangePlasma()
+ for(var/V in plc.settings)
+ plc.Randomize(V)
+
+/vs_control/proc/SetDefault(var/mob/user)
+ var/list/setting_choices = list("Plasma - Standard", "Plasma - Low Hazard", "Plasma - High Hazard", "Plasma - Oh Shit!",\
+ "ZAS - Normal", "ZAS - Forgiving", "ZAS - Dangerous", "ZAS - Hellish")
+ var/def = input(user, "Which of these presets should be used?") as null|anything in setting_choices
+ if(!def)
+ return
+ switch(def)
+ if("Plasma - Standard")
+ plc.CLOTH_CONTAMINATION = 1 //If this is on, plasma does damage by getting into cloth.
+ plc.PLASMAGUARD_ONLY = 0
+ plc.GENETIC_CORRUPTION = 0 //Chance of genetic corruption as well as toxic damage, X in 1000.
+ plc.SKIN_BURNS = 0 //Plasma has an effect similar to mustard gas on the un-suited.
+ plc.EYE_BURNS = 1 //Plasma burns the eyes of anyone not wearing eye protection.
+ plc.PLASMA_HALLUCINATION = 0
+ plc.CONTAMINATION_LOSS = 0.02
+
+ if("Plasma - Low Hazard")
+ plc.CLOTH_CONTAMINATION = 0 //If this is on, plasma does damage by getting into cloth.
+ plc.PLASMAGUARD_ONLY = 0
+ plc.GENETIC_CORRUPTION = 0 //Chance of genetic corruption as well as toxic damage, X in 1000
+ plc.SKIN_BURNS = 0 //Plasma has an effect similar to mustard gas on the un-suited.
+ plc.EYE_BURNS = 1 //Plasma burns the eyes of anyone not wearing eye protection.
+ plc.PLASMA_HALLUCINATION = 0
+ plc.CONTAMINATION_LOSS = 0.01
+
+ if("Plasma - High Hazard")
+ plc.CLOTH_CONTAMINATION = 1 //If this is on, plasma does damage by getting into cloth.
+ plc.PLASMAGUARD_ONLY = 0
+ plc.GENETIC_CORRUPTION = 0 //Chance of genetic corruption as well as toxic damage, X in 1000.
+ plc.SKIN_BURNS = 1 //Plasma has an effect similar to mustard gas on the un-suited.
+ plc.EYE_BURNS = 1 //Plasma burns the eyes of anyone not wearing eye protection.
+ plc.PLASMA_HALLUCINATION = 1
+ plc.CONTAMINATION_LOSS = 0.05
+
+ if("Plasma - Oh Shit!")
+ plc.CLOTH_CONTAMINATION = 1 //If this is on, plasma does damage by getting into cloth.
+ plc.PLASMAGUARD_ONLY = 1
+ plc.GENETIC_CORRUPTION = 5 //Chance of genetic corruption as well as toxic damage, X in 1000.
+ plc.SKIN_BURNS = 1 //Plasma has an effect similar to mustard gas on the un-suited.
+ plc.EYE_BURNS = 1 //Plasma burns the eyes of anyone not wearing eye protection.
+ plc.PLASMA_HALLUCINATION = 1
+ plc.CONTAMINATION_LOSS = 0.075
+
+ if("ZAS - Normal")
+ airflow_lightest_pressure = 20
+ airflow_light_pressure = 35
+ airflow_medium_pressure = 50
+ airflow_heavy_pressure = 65
+ airflow_dense_pressure = 85
+ airflow_stun_pressure = 60
+ airflow_stun_cooldown = 60
+ airflow_stun = 1
+ airflow_damage = 2
+ airflow_speed_decay = 1.5
+ airflow_delay = 30
+ airflow_mob_slowdown = 1
+
+ if("ZAS - Forgiving")
+ airflow_lightest_pressure = 45
+ airflow_light_pressure = 60
+ airflow_medium_pressure = 120
+ airflow_heavy_pressure = 110
+ airflow_dense_pressure = 200
+ airflow_stun_pressure = 150
+ airflow_stun_cooldown = 90
+ airflow_stun = 0.15
+ airflow_damage = 0.15
+ airflow_speed_decay = 1.5
+ airflow_delay = 50
+ airflow_mob_slowdown = 0
+
+ if("ZAS - Dangerous")
+ airflow_lightest_pressure = 15
+ airflow_light_pressure = 30
+ airflow_medium_pressure = 45
+ airflow_heavy_pressure = 55
+ airflow_dense_pressure = 70
+ airflow_stun_pressure = 50
+ airflow_stun_cooldown = 50
+ airflow_stun = 2
+ airflow_damage = 3
+ airflow_speed_decay = 1.2
+ airflow_delay = 25
+ airflow_mob_slowdown = 2
+
+ if("ZAS - Hellish")
+ airflow_lightest_pressure = 20
+ airflow_light_pressure = 30
+ airflow_medium_pressure = 40
+ airflow_heavy_pressure = 50
+ airflow_dense_pressure = 60
+ airflow_stun_pressure = 40
+ airflow_stun_cooldown = 40
+ airflow_stun = 3
+ airflow_damage = 4
+ airflow_speed_decay = 1
+ airflow_delay = 20
+ airflow_mob_slowdown = 3
+
+
+ world << "\blue [key_name(user)] changed the global plasma/ZAS settings to \"[def]\""
+
+/pl_control/var/list/settings = list()
+
+/pl_control/New()
+ . = ..()
+ settings = vars.Copy()
+
+ var/datum/D = new() //Ensure only unique vars are put through by making a datum and removing all common vars.
+ for(var/V in D.vars)
+ settings -= V
+
+ for(var/V in settings)
+ if(findtextEx(V,"_RANDOM") || findtextEx(V,"_DESC"))
+ settings -= V
+
+ settings -= "settings"
+
+/pl_control/proc/Randomize(V)
+ var/newvalue
+ if("[V]_RANDOM" in vars)
+ if(isnum(vars["[V]_RANDOM"]))
+ newvalue = prob(vars["[V]_RANDOM"])
+ else if(istext(vars["[V]_RANDOM"]))
+ var/txt = vars["[V]_RANDOM"]
+ if(findtextEx(txt,"PROB"))
+ txt = text2list(txt,"/")
+ txt[1] = replacetext(txt[1],"PROB","")
+ var/p = text2num(txt[1])
+ var/r = txt[2]
+ if(prob(p))
+ newvalue = roll(r)
+ else
+ newvalue = vars[V]
+ else if(findtextEx(txt,"PICK"))
+ txt = replacetext(txt,"PICK","")
+ txt = text2list(txt,",")
+ newvalue = pick(txt)
+ else
+ newvalue = roll(txt)
+ else
+ newvalue = vars[V]
+ vars[V] = newvalue
diff --git a/code/ZAS/ZAS_Turfs.dm b/code/ZAS/ZAS_Turfs.dm
index 2ed0478aba..0070a19c5d 100644
--- a/code/ZAS/ZAS_Turfs.dm
+++ b/code/ZAS/ZAS_Turfs.dm
@@ -1,278 +1,266 @@
-atom/var/pressure_resistance = ONE_ATMOSPHERE
-turf
+/atom/var/pressure_resistance = ONE_ATMOSPHERE
- var/zone/zone
+/turf/var/zone/zone
- assume_air(datum/gas_mixture/giver) //use this for machines to adjust air
- del(giver)
- return 0
+/turf/assume_air(datum/gas_mixture/giver) //use this for machines to adjust air
+ del(giver)
+ return 0
- return_air()
- //Create gas mixture to hold data for passing
- var/datum/gas_mixture/GM = new
+/turf/return_air()
+ //Create gas mixture to hold data for passing
+ var/datum/gas_mixture/GM = new
- GM.oxygen = oxygen
- GM.carbon_dioxide = carbon_dioxide
- GM.nitrogen = nitrogen
- GM.toxins = toxins
+ GM.oxygen = oxygen
+ GM.carbon_dioxide = carbon_dioxide
+ GM.nitrogen = nitrogen
+ GM.toxins = toxins
- GM.temperature = temperature
- GM.update_values()
+ GM.temperature = temperature
+ GM.update_values()
- return GM
+ return GM
- remove_air(amount as num)
- var/datum/gas_mixture/GM = new
+/turf/remove_air(amount as num)
+ var/datum/gas_mixture/GM = new
- var/sum = oxygen + carbon_dioxide + nitrogen + toxins
- if(sum>0)
- GM.oxygen = (oxygen/sum)*amount
- GM.carbon_dioxide = (carbon_dioxide/sum)*amount
- GM.nitrogen = (nitrogen/sum)*amount
- GM.toxins = (toxins/sum)*amount
+ var/sum = oxygen + carbon_dioxide + nitrogen + toxins
+ if(sum>0)
+ GM.oxygen = (oxygen/sum)*amount
+ GM.carbon_dioxide = (carbon_dioxide/sum)*amount
+ GM.nitrogen = (nitrogen/sum)*amount
+ GM.toxins = (toxins/sum)*amount
- GM.temperature = temperature
- GM.update_values()
+ GM.temperature = temperature
+ GM.update_values()
- return GM
+ return GM
-turf
- simulated
+/turf/simulated/var/current_graphic = null
- var/current_graphic = null
+/turf/simulated/var/tmp/datum/gas_mixture/air
- var/tmp
- datum/gas_mixture/air
+/turf/simulated/var/tmp/processing = 1
- processing = 1
+/turf/simulated/var/tmp/air_check_directions = 0 //Do not modify this, just add turf to air_master.tiles_to_update
- air_check_directions = 0 //Do not modify this, just add turf to air_master.tiles_to_update
+/turf/simulated/var/tmp/obj/fire/active_hotspot
- obj/fire/active_hotspot
+/turf/simulated/proc/update_visuals()
+ overlays = null
+ var/siding_icon_state = return_siding_icon_state()
+ if(siding_icon_state)
+ overlays += image('floors.dmi',siding_icon_state)
+ var/datum/gas_mixture/model = return_air()
+ switch(model.graphic)
+ if(1)
+ overlays.Add(plmaster) //TODO: Make invisible plasma an option
+ if(2)
+ overlays.Add(slmaster)
- proc/update_visuals()
- overlays = null
+/turf/simulated/New()
+ ..()
- var/siding_icon_state = return_siding_icon_state()
- if(siding_icon_state)
- overlays += image('floors.dmi',siding_icon_state)
- var/datum/gas_mixture/model = return_air()
- switch(model.graphic)
- if(1)
- overlays.Add(plmaster) //TODO: Make invisible plasma an option
- if(2)
- overlays.Add(slmaster)
+ if(!blocks_air)
+ air = new
+ air.oxygen = oxygen
+ air.carbon_dioxide = carbon_dioxide
+ air.nitrogen = nitrogen
+ air.toxins = toxins
+ air.temperature = temperature
+ air.update_values()
- New()
- ..()
-
- if(!blocks_air)
- air = new
-
- air.oxygen = oxygen
- air.carbon_dioxide = carbon_dioxide
- air.nitrogen = nitrogen
- air.toxins = toxins
-
- air.temperature = temperature
- air.update_values()
-
- if(air_master)
- air_master.tiles_to_update.Add(src)
-
- else
- if(air_master)
- for(var/direction in cardinal)
- var/turf/simulated/floor/target = get_step(src,direction)
- if(istype(target))
- air_master.tiles_to_update |= target
-
- Del()
- if(active_hotspot)
- del(active_hotspot)
- if(blocks_air)
- for(var/direction in list(NORTH, SOUTH, EAST, WEST))
- var/turf/simulated/tile = get_step(src,direction)
- if(istype(tile) && !tile.blocks_air)
- air_master.tiles_to_update.Add(tile)
- ..()
-
- assume_air(datum/gas_mixture/giver)
- if(!giver) return 0
- if(zone)
- zone.air.merge(giver)
- return 1
- else
- return ..()
-
- return_air()
- if(zone)
- return zone.air
- else if(air)
- return air
-
- else
- return ..()
-
- remove_air(amount as num)
- if(zone)
- var/datum/gas_mixture/removed = null
- removed = zone.air.remove(amount)
- return removed
- else if(air)
- var/datum/gas_mixture/removed = null
- removed = air.remove(amount)
-
- if(air.check_tile_graphic())
- update_visuals(air)
- return removed
-
- else
- return ..()
-
- proc/update_air_properties()
- var/air_directions_archived = air_check_directions
- air_check_directions = 0
+ if(air_master)
+ air_master.tiles_to_update.Add(src)
+ else
+ if(air_master)
for(var/direction in cardinal)
- if(ZAirPass(get_step(src,direction)))
- air_check_directions |= direction
+ var/turf/simulated/floor/target = get_step(src,direction)
+ if(istype(target))
+ air_master.tiles_to_update |= target
- if(!zone && !blocks_air) //No zone, but not a wall.
- for(var/direction in DoorDirections) //Check door directions first.
- if(air_check_directions&direction)
- var/turf/simulated/T = get_step(src,direction)
- if(!istype(T))
- continue
- if(T.zone)
- T.zone.AddTurf(src)
- break
- if(!zone) //Still no zone
- for(var/direction in CounterDoorDirections) //Check the others second.
- if(air_check_directions&direction)
- var/turf/simulated/T = get_step(src,direction)
- if(!istype(T))
- continue
- if(T.zone)
- T.zone.AddTurf(src)
- break
- if(!zone) //No zone found, new zone!
- new/zone(src)
- if(!zone) //Still no zone, the floodfill determined it is not part of a larger zone. Force a zone on it.
- new/zone(list(src))
+/turf/simulated/Del()
+ if(active_hotspot)
+ del(active_hotspot)
+ if(blocks_air)
+ for(var/direction in list(NORTH, SOUTH, EAST, WEST))
+ var/turf/simulated/tile = get_step(src,direction)
+ if(istype(tile) && !tile.blocks_air)
+ air_master.tiles_to_update.Add(tile)
+ ..()
- //Check pass sanity of the connections.
- if("\ref[src]" in air_master.turfs_with_connections)
- for(var/connection/C in air_master.turfs_with_connections["\ref[src]"])
- air_master.connections_to_check |= C
+/turf/simulated/assume_air(datum/gas_mixture/giver)
+ if(!giver) return 0
+ if(zone)
+ zone.air.merge(giver)
+ return 1
+ else
+ return ..()
- if(zone && !zone.rebuild)
- for(var/direction in cardinal)
- var/turf/T = get_step(src,direction)
+/turf/simulated/return_air()
+ if(zone)
+ return zone.air
+ else if(air)
+ return air
+
+ else
+ return ..()
+
+/turf/simulated/remove_air(amount as num)
+ if(zone)
+ var/datum/gas_mixture/removed = null
+ removed = zone.air.remove(amount)
+ return removed
+ else if(air)
+ var/datum/gas_mixture/removed = null
+ removed = air.remove(amount)
+
+ if(air.check_tile_graphic())
+ update_visuals(air)
+ return removed
+
+ else
+ return ..()
+
+/turf/simulated/proc/update_air_properties()
+ var/air_directions_archived = air_check_directions
+ air_check_directions = 0
+
+ for(var/direction in cardinal)
+ if(ZAirPass(get_step(src,direction)))
+ air_check_directions |= direction
+
+ if(!zone && !blocks_air) //No zone, but not a wall.
+ for(var/direction in DoorDirections) //Check door directions first.
+ if(air_check_directions&direction)
+ var/turf/simulated/T = get_step(src,direction)
+ if(!istype(T))
+ continue
+ if(T.zone)
+ T.zone.AddTurf(src)
+ break
+ if(!zone) //Still no zone
+ for(var/direction in CounterDoorDirections) //Check the others second.
+ if(air_check_directions&direction)
+ var/turf/simulated/T = get_step(src,direction)
if(!istype(T))
continue
+ if(T.zone)
+ T.zone.AddTurf(src)
+ break
+ if(!zone) //No zone found, new zone!
+ new/zone(src)
+ if(!zone) //Still no zone, the floodfill determined it is not part of a larger zone. Force a zone on it.
+ new/zone(list(src))
- //I can connect to air in this direction
- if(air_check_directions&direction)
+ //Check pass sanity of the connections.
+ if("\ref[src]" in air_master.turfs_with_connections)
+ for(var/connection/C in air_master.turfs_with_connections["\ref[src]"])
+ air_master.connections_to_check |= C
- //If either block air, we must look to see if the adjacent turfs need rebuilt.
- if(!CanPass(null, T, 0, 0))
+ if(zone && !zone.rebuild)
+ for(var/direction in cardinal)
+ var/turf/T = get_step(src,direction)
+ if(!istype(T))
+ continue
- //Target blocks air
- if(!T.CanPass(null, T, 0, 0))
- var/turf/NT = get_step(T, direction)
+ //I can connect to air in this direction
+ if(air_check_directions&direction)
- //If that turf is in my zone still, rebuild.
- if(istype(NT,/turf/simulated) && NT in zone.contents)
- zone.rebuild = 1
+ //If either block air, we must look to see if the adjacent turfs need rebuilt.
+ if(!CanPass(null, T, 0, 0))
- //If that is an unsimulated tile in my zone, see if we need to rebuild or just remove.
- else if(istype(NT) && NT in zone.unsimulated_tiles)
- var/consider_rebuild = 0
- for(var/d in cardinal)
- var/turf/UT = get_step(NT,d)
- if(istype(UT, /turf/simulated) && UT.zone == zone && UT.CanPass(null, NT, 0, 0)) //If we find a neighboring tile that is in the same zone, check if we need to rebuild
- consider_rebuild = 1
- break
- if(consider_rebuild)
- zone.rebuild = 1 //Gotta check if we need to rebuild, dammit
- else
- zone.RemoveTurf(NT) //Not adjacent to anything, and unsimulated. Goodbye~
-
- //To make a closed connection through closed door.
- ZConnect(T, src)
-
- //If I block air.
- else if(T.zone && !T.zone.rebuild)
- var/turf/NT = get_step(src, reverse_direction(direction))
-
- //If I am splitting a zone, rebuild.
- if(istype(NT,/turf/simulated) && (NT in T.zone.contents || (NT.zone && T in NT.zone.contents)))
- T.zone.rebuild = 1
-
- //If NT is unsimulated, parse if I should remove it or rebuild.
- else if(istype(NT) && NT in T.zone.unsimulated_tiles)
- var/consider_rebuild = 0
- for(var/d in cardinal)
- var/turf/UT = get_step(NT,d)
- if(istype(UT, /turf/simulated) && UT.zone == T.zone && UT.CanPass(null, NT, 0, 0)) //If we find a neighboring tile that is in the same zone, check if we need to rebuild
- consider_rebuild = 1
- break
-
- //Needs rebuilt.
- if(consider_rebuild)
- T.zone.rebuild = 1
-
- //Not adjacent to anything, and unsimulated. Goodbye~
- else
- T.zone.RemoveTurf(NT)
-
- else
- //Produce connection through open door.
- ZConnect(src,T)
-
- //Something like a wall was built, changing the geometry.
- else if(air_directions_archived&direction)
+ //Target blocks air
+ if(!T.CanPass(null, T, 0, 0))
var/turf/NT = get_step(T, direction)
- //If the tile is in our own zone, and we cannot connect to it, better rebuild.
+ //If that turf is in my zone still, rebuild.
if(istype(NT,/turf/simulated) && NT in zone.contents)
zone.rebuild = 1
- //Parse if we need to remove the tile, or rebuild the zone.
+ //If that is an unsimulated tile in my zone, see if we need to rebuild or just remove.
else if(istype(NT) && NT in zone.unsimulated_tiles)
var/consider_rebuild = 0
-
- //Loop through all neighboring turfs to see if we should remove the turf or just rebuild.
for(var/d in cardinal)
var/turf/UT = get_step(NT,d)
+ if(istype(UT, /turf/simulated) && UT.zone == zone && UT.CanPass(null, NT, 0, 0)) //If we find a neighboring tile that is in the same zone, check if we need to rebuild
+ consider_rebuild = 1
+ break
+ if(consider_rebuild)
+ zone.rebuild = 1 //Gotta check if we need to rebuild, dammit
+ else
+ zone.RemoveTurf(NT) //Not adjacent to anything, and unsimulated. Goodbye~
- //If we find a neighboring tile that is in the same zone, rebuild
- if(istype(UT, /turf/simulated) && UT.zone == zone && UT.CanPass(null, NT, 0, 0))
+ //To make a closed connection through closed door.
+ ZConnect(T, src)
+
+ //If I block air.
+ else if(T.zone && !T.zone.rebuild)
+ var/turf/NT = get_step(src, reverse_direction(direction))
+
+ //If I am splitting a zone, rebuild.
+ if(istype(NT,/turf/simulated) && (NT in T.zone.contents || (NT.zone && T in NT.zone.contents)))
+ T.zone.rebuild = 1
+
+ //If NT is unsimulated, parse if I should remove it or rebuild.
+ else if(istype(NT) && NT in T.zone.unsimulated_tiles)
+ var/consider_rebuild = 0
+ for(var/d in cardinal)
+ var/turf/UT = get_step(NT,d)
+ if(istype(UT, /turf/simulated) && UT.zone == T.zone && UT.CanPass(null, NT, 0, 0)) //If we find a neighboring tile that is in the same zone, check if we need to rebuild
consider_rebuild = 1
break
- //The unsimulated turf is adjacent to another one of our zone's turfs,
- // better rebuild to be sure we didn't get cut in twain
+ //Needs rebuilt.
if(consider_rebuild)
- zone.rebuild = 1
+ T.zone.rebuild = 1
//Not adjacent to anything, and unsimulated. Goodbye~
else
- zone.RemoveTurf(NT)
+ T.zone.RemoveTurf(NT)
- if(air_check_directions)
- processing = 1
- else
- processing = 0
- return 1
+ else
+ //Produce connection through open door.
+ ZConnect(src,T)
+ //Something like a wall was built, changing the geometry.
+ else if(air_directions_archived&direction)
+ var/turf/NT = get_step(T, direction)
+ //If the tile is in our own zone, and we cannot connect to it, better rebuild.
+ if(istype(NT,/turf/simulated) && NT in zone.contents)
+ zone.rebuild = 1
+ //Parse if we need to remove the tile, or rebuild the zone.
+ else if(istype(NT) && NT in zone.unsimulated_tiles)
+ var/consider_rebuild = 0
+ //Loop through all neighboring turfs to see if we should remove the turf or just rebuild.
+ for(var/d in cardinal)
+ var/turf/UT = get_step(NT,d)
+
+ //If we find a neighboring tile that is in the same zone, rebuild
+ if(istype(UT, /turf/simulated) && UT.zone == zone && UT.CanPass(null, NT, 0, 0))
+ consider_rebuild = 1
+ break
+
+ //The unsimulated turf is adjacent to another one of our zone's turfs,
+ // better rebuild to be sure we didn't get cut in twain
+ if(consider_rebuild)
+ zone.rebuild = 1
+
+ //Not adjacent to anything, and unsimulated. Goodbye~
+ else
+ zone.RemoveTurf(NT)
+
+ if(air_check_directions)
+ processing = 1
+ else
+ processing = 0
+ return 1
/turf/proc/HasDoor(turf/O)
//Checks for the presence of doors, used for zone spreading and connection.
@@ -289,7 +277,7 @@ turf
else
return 1
-turf/proc/ZCanPass(turf/simulated/T, var/include_space = 0)
+/turf/proc/ZCanPass(turf/simulated/T, var/include_space = 0)
//Fairly standard pass checks for turfs, objects and directional windows. Also stops at the edge of space.
if(!istype(T))
return 0
@@ -314,7 +302,7 @@ turf/proc/ZCanPass(turf/simulated/T, var/include_space = 0)
return 1
-turf/proc/ZAirPass(turf/T)
+/turf/proc/ZAirPass(turf/T)
//Fairly standard pass checks for turfs, objects and directional windows.
if(!istype(T))
return 0
@@ -336,7 +324,6 @@ turf/proc/ZAirPass(turf/T)
return 1
-
/*UNUSED
/turf/proc/check_connections()
//Checks for new connections that can be made.
diff --git a/code/ZAS/ZAS_Zones.dm b/code/ZAS/ZAS_Zones.dm
index 2f5d564b3b..026f6e3d45 100644
--- a/code/ZAS/ZAS_Zones.dm
+++ b/code/ZAS/ZAS_Zones.dm
@@ -2,129 +2,126 @@ var/list/zones = list()
var/list/DoorDirections = list(NORTH,WEST) //Which directions doors turfs can connect to zones
var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs can connect to zones
-zone
-
- var
- dbg_output = 0 //Enables debug output.
- rebuild = 0 //If 1, zone will be rebuilt on next process. Not sure if used.
- datum/gas_mixture/air //The air contents of the zone.
- list/contents //All the tiles that are contained in this zone.
- list/connections // /connection objects which refer to connections with other zones, e.g. through a door.
- list/connected_zones //Parallels connections, but lists zones to which this one is connected and the number
+/zone
+ var/dbg_output = 0 //Enables debug output.
+ var/rebuild = 0 //If 1, zone will be rebuilt on next process. Not sure if used.
+ var/datum/gas_mixture/air //The air contents of the zone.
+ var/list/contents //All the tiles that are contained in this zone.
+ var/list/connections // /connection objects which refer to connections with other zones, e.g. through a door.
+ var/list/connected_zones //Parallels connections, but lists zones to which this one is connected and the number
//of points they're connected at.
- list/closed_connection_zones //Same as connected_zones, but for zones where the door or whatever is closed.
- list/unsimulated_tiles // Any space tiles in this list will cause air to flow out.
- last_update = 0
- progress = "nothing"
-
- // To make sure you're not spammed to death by airflow sound effects
- tmp/playsound_cooldown = 0
+ var/list/closed_connection_zones //Same as connected_zones, but for zones where the door or whatever is closed.
+ var/list/unsimulated_tiles // Any space tiles in this list will cause air to flow out.
+ var/last_update = 0
+ var/progress = "nothing"
//CREATION AND DELETION
- New(turf/start)
- . = ..()
- //Get the turfs that are part of the zone using a floodfill method
- if(istype(start,/list))
- contents = start
- else
- contents = FloodFill(start)
+/zone/New(turf/start)
+ . = ..()
+ //Get the turfs that are part of the zone using a floodfill method
+ if(istype(start,/list))
+ contents = start
+ else
+ contents = FloodFill(start)
- //Change all the zone vars of the turfs, check for space to be added to unsimulated_tiles.
- for(var/turf/T in contents)
- if(T.zone && T.zone != src)
- T.zone.RemoveTurf(T)
- T.zone = src
- if(!istype(T,/turf/simulated))
- AddTurf(T)
+ //Change all the zone vars of the turfs, check for space to be added to unsimulated_tiles.
+ for(var/turf/T in contents)
+ if(T.zone && T.zone != src)
+ T.zone.RemoveTurf(T)
+ T.zone = src
+ if(!istype(T,/turf/simulated))
+ AddTurf(T)
- //Generate the gas_mixture for use in txhis zone by using the average of the gases
- //defined at startup.
- air = new
- var/members = contents.len
- for(var/turf/simulated/T in contents)
- air.oxygen += T.oxygen / members
- air.nitrogen += T.nitrogen / members
- air.carbon_dioxide += T.carbon_dioxide / members
- air.toxins += T.toxins / members
- air.temperature += T.temperature / members
- air.group_multiplier = contents.len
- air.update_values()
+ //Generate the gas_mixture for use in txhis zone by using the average of the gases
+ //defined at startup.
+ air = new
+ air.group_multiplier = contents.len
+ for(var/turf/simulated/T in contents)
+ air.oxygen += T.oxygen / air.group_multiplier
+ air.nitrogen += T.nitrogen / air.group_multiplier
+ air.carbon_dioxide += T.carbon_dioxide / air.group_multiplier
+ air.toxins += T.toxins / air.group_multiplier
+ air.temperature += T.temperature / air.group_multiplier
+ air.update_values()
- //Add this zone to the global list.
- zones.Add(src)
+ //Add this zone to the global list.
+ zones.Add(src)
//LEGACY, DO NOT USE. Use the SoftDelete proc.
- Del()
- //Ensuring the zone list doesn't get clogged with null values.
- for(var/turf/simulated/T in contents)
- RemoveTurf(T)
- air_master.tiles_to_reconsider_zones += T
- for(var/zone/Z in connected_zones)
- if(src in Z.connected_zones)
- Z.connected_zones.Remove(src)
- for(var/connection/C in connections)
- air_master.connections_to_check += C
- zones.Remove(src)
- air = null
- . = ..()
+/zone/Del()
+ //Ensuring the zone list doesn't get clogged with null values.
+ for(var/turf/simulated/T in contents)
+ RemoveTurf(T)
+ air_master.tiles_to_reconsider_zones += T
+ for(var/zone/Z in connected_zones)
+ if(src in Z.connected_zones)
+ Z.connected_zones.Remove(src)
+ for(var/connection/C in connections)
+ air_master.connections_to_check += C
+ zones.Remove(src)
+ air = null
+ . = ..()
//Handles deletion via garbage collection.
- proc/SoftDelete()
- zones.Remove(src)
- air = null
+/zone/proc/SoftDelete()
+ zones.Remove(src)
+ air = null
- //Ensuring the zone list doesn't get clogged with null values.
- for(var/turf/simulated/T in contents)
- RemoveTurf(T)
- air_master.tiles_to_reconsider_zones += T
+ //Ensuring the zone list doesn't get clogged with null values.
+ for(var/turf/simulated/T in contents)
+ RemoveTurf(T)
+ air_master.tiles_to_reconsider_zones += T
- //Removing zone connections and scheduling connection cleanup
- for(var/zone/Z in connected_zones)
- if(src in Z.connected_zones)
- Z.connected_zones.Remove(src)
- for(var/connection/C in connections)
- air_master.connections_to_check += C
+ //Removing zone connections and scheduling connection cleanup
+ for(var/zone/Z in connected_zones)
+ if(src in Z.connected_zones)
+ Z.connected_zones.Remove(src)
+ connected_zones = null
- return 1
+ for(var/connection/C in connections)
+ air_master.connections_to_check += C
+ connections = null
+
+ return 1
//ZONE MANAGEMENT FUNCTIONS
- proc/AddTurf(turf/T)
- //Adds the turf to contents, increases the size of the zone, and sets the zone var.
- if(istype(T, /turf/simulated))
- if(T in contents)
- return
- if(T.zone)
- T.zone.RemoveTurf(T)
- contents += T
- if(air)
- air.group_multiplier++
- T.zone = src
- else
- if(!unsimulated_tiles)
- unsimulated_tiles = list()
- else if(T in unsimulated_tiles)
- return
- unsimulated_tiles += T
- contents -= T
+/zone/proc/AddTurf(turf/T)
+ //Adds the turf to contents, increases the size of the zone, and sets the zone var.
+ if(istype(T, /turf/simulated))
+ if(T in contents)
+ return
+ if(T.zone)
+ T.zone.RemoveTurf(T)
+ contents += T
+ if(air)
+ air.group_multiplier++
+ T.zone = src
+ else
+ if(!unsimulated_tiles)
+ unsimulated_tiles = list()
+ else if(T in unsimulated_tiles)
+ return
+ unsimulated_tiles += T
+ contents -= T
- proc/RemoveTurf(turf/T)
- //Same, but in reverse.
- if(istype(T, /turf/simulated))
- if(!(T in contents))
- return
- contents -= T
- if(air)
- air.group_multiplier--
- if(T.zone == src)
- T.zone = null
- else if(unsimulated_tiles)
- unsimulated_tiles -= T
- if(!unsimulated_tiles.len)
- unsimulated_tiles = null
+/zone/proc/RemoveTurf(turf/T)
+ //Same, but in reverse.
+ if(istype(T, /turf/simulated))
+ if(!(T in contents))
+ return
+ contents -= T
+ if(air)
+ air.group_multiplier--
+ if(T.zone == src)
+ T.zone = null
+ else if(unsimulated_tiles)
+ unsimulated_tiles -= T
+ if(!unsimulated_tiles.len)
+ unsimulated_tiles = null
//////////////
//PROCESSING//
@@ -132,7 +129,7 @@ zone
#define QUANTIZE(variable) (round(variable,0.0001))
-zone/proc/process()
+/zone/proc/process()
. = 1
progress = "problem with: SoftDelete()"
@@ -151,7 +148,7 @@ zone/proc/process()
if(!contents.len) //If we got soft deleted.
return
- progress = "problem with: air.adjust()"
+ progress = "problem with: air regeneration"
//Sometimes explosions will cause the air to be deleted for some reason.
if(!air)
@@ -162,36 +159,23 @@ zone/proc/process()
air.total_moles()
world.log << "Air object lost in zone. Regenerating."
- progress = "problem with: ShareSpace()"
+ progress = "problem with: ShareSpace()"
if(unsimulated_tiles)
if(locate(/turf/simulated) in unsimulated_tiles)
for(var/turf/simulated/T in unsimulated_tiles)
- RemoveTurf(T)
- if(unsimulated_tiles)
+ unsimulated_tiles -= T
+
+ if(unsimulated_tiles.len)
var/moved_air = ShareSpace(air,unsimulated_tiles)
- // Only play a sound effect every once in a while
- if(playsound_cooldown <= world.time)
- // Play a nice sound effect at one of the bordering turfs
-
- playsound_cooldown = world.time + rand(30, 70)
-
- var/turf/random_border = pick(contents)
- play_wind_sound(random_border, abs(moved_air))
-
if(moved_air > vsc.airflow_lightest_pressure)
AirflowSpace(src)
-
- progress = "problem with: air.react()"
-
- //React the air here.
- //Handled by fire, no need for this.
-// air.react(null,0)
+ else
+ unsimulated_tiles = null
//Check the graphic.
-
progress = "problem with: modifying turf graphics"
air.graphic = 0
@@ -246,12 +230,13 @@ zone/proc/process()
//Check if the connection is valid first.
if(!C.Cleanup())
continue
+
//Do merging if conditions are met. Specifically, if there's a non-door connection
//to somewhere with space, the zones are merged regardless of equilibrium, to speed
//up spacing in areas with double-plated windows.
if(C && C.A.zone && C.B.zone)
//indirect = 2 is a direct connection.
- if(C.indirect == 2 )
+ if( C.indirect == 2 )
if(C.A.zone.air.compare(C.B.zone.air) || unsimulated_tiles)
ZMerge(C.A.zone,C.B.zone)
@@ -259,18 +244,13 @@ zone/proc/process()
//Share some
for(var/zone/Z in connected_zones)
+ //If that zone has already processed, skip it.
+ if(Z.last_update > last_update)
+ continue
+
if(air && Z.air)
//Ensure we're not doing pointless calculations on equilibrium zones.
var/moles_delta = abs(air.total_moles() - Z.air.total_moles())
- if(moles_delta > 0.1)
- // Only play a sound effect every once in a while
- if(playsound_cooldown <= world.time)
- // Play a nice sound effect at one of the bordering turfs
-
- playsound_cooldown = world.time + rand(30, 70)
-
- var/turf/random_border = pick(contents)
- play_wind_sound(random_border, abs(moles_delta))
if(moles_delta > 0.1 || abs(air.temperature - Z.air.temperature) > 0.1)
if(abs(Z.air.return_pressure() - air.return_pressure()) > vsc.airflow_lightest_pressure)
Airflow(src,Z)
@@ -284,7 +264,7 @@ zone/proc/process()
for(var/zone/Z in closed_connection_zones)
if(air && Z.air)
- if( abs(air.temperature - Z.air.temperature) > 10 )
+ if( abs(air.temperature - Z.air.temperature) > vsc.connection_temperature_delta )
ShareHeat(air, Z.air, closed_connection_zones[Z])
progress = "all components completed successfully, the problem is not here"
@@ -293,7 +273,7 @@ zone/proc/process()
//Air Movement//
////////////////
-var/list/sharing_lookup_table = list(0.15, 0.20, 0.24, 0.27, 0.30, 0.33)
+var/list/sharing_lookup_table = list(0.30, 0.40, 0.48, 0.54, 0.60, 0.66)
proc/ShareRatio(datum/gas_mixture/A, datum/gas_mixture/B, connecting_tiles)
//Shares a specific ratio of gas between mixtures using simple weighted averages.
@@ -423,7 +403,9 @@ proc/ShareSpace(datum/gas_mixture/A, list/unsimulated_tiles, dbg_output)
if(sharing_lookup_table.len >= unsimulated_tiles.len) //6 or more interconnecting tiles will max at 42% of air moved per tick.
ratio = sharing_lookup_table[unsimulated_tiles.len]
- ratio *= 2
+
+ //We need to adjust it to account for the insulation settings.
+ ratio *= 1 - vsc.connection_insulation
A.oxygen = max(0, (A.oxygen - oxy_avg) * (1 - ratio) + oxy_avg )
A.nitrogen = max(0, (A.nitrogen - nit_avg) * (1 - ratio) + nit_avg )
@@ -543,22 +525,6 @@ zone/proc/Rebuild()
if(istype(T) && T.zone && S.CanPass(null, T, 0, 0))
T.zone.AddTurf(S)
-
-proc/play_wind_sound(var/turf/random_border, var/n)
- if(random_border)
- var/windsound = 'sound/effects/wind/wind_2_1.ogg'
- switch(n)
- if(31 to 40)
- windsound = pick('sound/effects/wind/wind_2_1.ogg', 'sound/effects/wind/wind_2_2.ogg')
- if(41 to 50)
- windsound = pick('sound/effects/wind/wind_3_1.ogg')
- if(51 to 60)
- windsound = pick('sound/effects/wind/wind_4_1.ogg', 'sound/effects/wind/wind_4_2.ogg')
- if(61 to 1000000)
- windsound = pick('sound/effects/wind/wind_5_1.ogg')
-
- playsound(random_border, windsound, 50, 1, 1)
-
//UNUSED
/*
zone/proc/connected_zones()
diff --git a/code/controllers/master_controller.dm b/code/controllers/master_controller.dm
index c22bf1e2dd..22a905a207 100644
--- a/code/controllers/master_controller.dm
+++ b/code/controllers/master_controller.dm
@@ -132,12 +132,12 @@ datum/controller/game_controller/proc/process()
//src.set_debug_state("Air Master")
air_master.current_cycle++
- var/success = air_master.tick() //Changed so that a runtime does not crash the ticker.
- if(!success) //Runtimed.
+ if(!air_master.tick()) //Runtimed.
air_master.failed_ticks++
if(air_master.failed_ticks > 5)
world << "RUNTIMES IN ATMOS TICKER. Killing air simulation!"
- message_admins("ZASALERT: unable run [air_master.tick_progress], tell someone about this!")
+ world.log << "### ZAS SHUTDOWN"
+ message_admins("ZASALERT: unable to run [air_master.tick_progress], shutting down!")
log_admin("ZASALERT: unable run zone/process() -- [air_master.tick_progress]")
air_processing_killed = 1
air_master.failed_ticks = 0
diff --git a/code/game/mecha/mech_fabricator.dm b/code/game/mecha/mech_fabricator.dm
index 5bf4664822..7b72a5597b 100644
--- a/code/game/mecha/mech_fabricator.dm
+++ b/code/game/mecha/mech_fabricator.dm
@@ -49,7 +49,8 @@
/obj/item/robot_parts/robot_component/radio,
/obj/item/robot_parts/robot_component/actuator,
/obj/item/robot_parts/robot_component/diagnosis_unit,
- /obj/item/robot_parts/robot_component/camera
+ /obj/item/robot_parts/robot_component/camera,
+ /obj/item/robot_parts/robot_component/armour
),
"Ripley"=list(
/obj/item/mecha_parts/chassis/ripley,
diff --git a/code/modules/flufftext/Hallucination.dm b/code/modules/flufftext/Hallucination.dm
index 0aa2b06a5f..18e4f2916a 100644
--- a/code/modules/flufftext/Hallucination.dm
+++ b/code/modules/flufftext/Hallucination.dm
@@ -77,7 +77,9 @@ mob/living/carbon/proc/handle_hallucinations()
halitem.name = "Flashbang"
if(client) client.screen += halitem
spawn(rand(100,250))
- del halitem
+ if(client)
+ client.screen -= halitem
+ halitem = null
if(26 to 40)
//Flashes of danger
//src << "Danger Flash"
diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm
index 7e41d6936d..205dcf5b34 100644
--- a/code/modules/mob/living/carbon/human/life.dm
+++ b/code/modules/mob/living/carbon/human/life.dm
@@ -998,7 +998,7 @@
sleeping = max(sleeping-1, 0)
blinded = 1
stat = UNCONSCIOUS
- if( prob(10) && health && !hal_crit )
+ if( prob(2) && health && !hal_crit )
spawn(0)
emote("snore")
else if(resting)
diff --git a/code/modules/surgery/generic.dm b/code/modules/surgery/generic.dm
index e46bff882d..ede924d8b4 100644
--- a/code/modules/surgery/generic.dm
+++ b/code/modules/surgery/generic.dm
@@ -86,7 +86,7 @@
fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
var/datum/organ/external/affected = target.get_organ(target_zone)
- user.visible_message("\red [user]'s hand slips, tearing blood vessals and causing massive bleeding in [target]'s [affected.display_name] with the \[tool]!", \
+ user.visible_message("\red [user]'s hand slips, tearing blood vessals and causing massive bleeding in [target]'s [affected.display_name] with \the [tool]!", \
"\red Your hand slips, tearing blood vessels and causing massive bleeding in [target]'s [affected.display_name] with \the [tool]!",)
affected.createwound(CUT, 10)
@@ -102,7 +102,7 @@
can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
var/datum/organ/external/affected = target.get_organ(target_zone)
- return ..() && affected.open < 2 && !(affected.status & ORGAN_BLEEDING)
+ return ..() && affected.open == 1 && !(affected.status & ORGAN_BLEEDING)
begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
var/datum/organ/external/affected = target.get_organ(target_zone)
diff --git a/code/setup.dm b/code/setup.dm
index 78d845436d..8afcbe689a 100644
--- a/code/setup.dm
+++ b/code/setup.dm
@@ -627,7 +627,7 @@ var/list/TAGGERLOCATIONS = list("Disposals",
#define CHAT_LOOC 4096
-#define TOGGLES_DEFAULT (SOUND_ADMINHELP|SOUND_MIDI|SOUND_AMBIENCE|SOUND_LOBBY|CHAT_OOC|CHAT_DEAD|CHAT_GHOSTEARS|CHAT_GHOSTSIGHT|CHAT_PRAYER|CHAT_RADIO|CHAT_ATTACKLOGS)
+#define TOGGLES_DEFAULT (SOUND_ADMINHELP|SOUND_MIDI|SOUND_AMBIENCE|SOUND_LOBBY|CHAT_OOC|CHAT_DEAD|CHAT_GHOSTEARS|CHAT_GHOSTSIGHT|CHAT_PRAYER|CHAT_RADIO|CHAT_ATTACKLOGS|CHAT_LOOC)
#define BE_TRAITOR 1
#define BE_OPERATIVE 2