From b06049f8b72ab7e9beec9f41258fb6ea507dcf54 Mon Sep 17 00:00:00 2001 From: Kreastr Date: Mon, 10 Dec 2012 15:09:32 +0200 Subject: [PATCH] New way of transferring air between zones. Now every zone can trigger group sharing. In group sharing the gases and temperatures are transfered based on average between all connected zones avoiding "slow transfer through bottlenecks" and processing order problems. The speed of transfer decays with total volume of connected zones. The old way is kept to generate pressure differences for airflows. --- code/ZAS/Definition.dm | 3 +- code/ZAS/FEA_system.dm | 4 +++ code/ZAS/Processing.dm | 77 +++++++++++++++++++++++++++++++++++++++++- 3 files changed, 82 insertions(+), 2 deletions(-) diff --git a/code/ZAS/Definition.dm b/code/ZAS/Definition.dm index 82c8b75..ee1a935 100644 --- a/code/ZAS/Definition.dm +++ b/code/ZAS/Definition.dm @@ -14,4 +14,5 @@ zone list/connected_zones //Parallels connections, but lists zones to which this one is connected and the number //of points they're connected at. list/space_tiles // Any space tiles in this list will cause air to flow out. - last_update = 0 \ No newline at end of file + last_update = 0 + ShareRequired = 0 \ No newline at end of file diff --git a/code/ZAS/FEA_system.dm b/code/ZAS/FEA_system.dm index e2c9d71..c691c70 100644 --- a/code/ZAS/FEA_system.dm +++ b/code/ZAS/FEA_system.dm @@ -192,6 +192,10 @@ datum if(. && Z && !output) . = 0 + for(var/zone/Z in zones) + if(Z.ShareRequired) + Z.GroupShare() + for(var/obj/fire/F in active_hotspots) var/output = F.process() if(. && F && !output) diff --git a/code/ZAS/Processing.dm b/code/ZAS/Processing.dm index 8d374e0..1272e8f 100644 --- a/code/ZAS/Processing.dm +++ b/code/ZAS/Processing.dm @@ -1,4 +1,6 @@ #define QUANTIZE(variable) (round(variable,0.0001)) + + zone/proc/process() . = 1 @@ -82,16 +84,89 @@ zone/proc/process() if(C.A.zone.air.compare(C.B.zone.air) || total_space) ZMerge(C.A.zone,C.B.zone) - //Share some + ShareRequired = 0 + //Share test for(var/zone/Z in connected_zones) //Ensure we're not doing pointless calculations on equilibrium zones. if(abs(air.total_moles - Z.air.total_moles) > 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) ShareRatio( air , Z.air , connected_zones[Z]*vsc.zone_share_percent/200 ) + ShareRequired = 1 //Divided by 200 since each zone is processed. Each connection is considered twice //Space tiles force it to try and move twice as much air. +zone/proc/GroupShare() + var/list/Cluster = new/list() + ShareRequired = 0 + Cluster += src + Cluster = JoinCluster(Cluster) + + var/oxy = 0 + var/nitro = 0 + var/co2 = 0 + var/plasma = 0 + var/size = 0 + var/heat = 0 + var/heatcapacity = 0 + var/list/traceavg = new/list() + + for (var/zone/Z in Cluster) + var/zsize = max(1,Z.air.group_multiplier) + oxy += Z.air.oxygen*zsize + nitro += Z.air.nitrogen*zsize + co2 += Z.air.carbon_dioxide*zsize + plasma += Z.air.toxins*zsize + heat += Z.air.temperature*Z.air.heat_capacity()*zsize + heatcapacity += Z.air.heat_capacity()*zsize + size += zsize + for (var/datum/gas/G in Z.air.trace_gases) + var/datum/gas/avgG = locate(G.type) in traceavg + if (avgG) + avgG.moles += G.moles*zsize + else + avgG = new G.type + avgG.moles += G.moles*zsize + traceavg += avgG + + oxy /= size + nitro /= size + plasma /= size + co2 /= size + heat /= heatcapacity //now it is actually an average temperature. + for (var/datum/gas/G in traceavg) + G.moles /= size + + //Each 40 tiles of Cluster size increase the convection process length by 100% + var/ratio=vsc.zone_share_percent/(100+size*2.5) + + for (var/zone/Z in Cluster) + Z.air.oxygen = (Z.air.oxygen - oxy) * (1-ratio) + oxy + Z.air.nitrogen = (Z.air.nitrogen - nitro) * (1-ratio) + nitro + Z.air.carbon_dioxide = (Z.air.carbon_dioxide - co2) * (1-ratio) + co2 + Z.air.toxins = (Z.air.toxins - plasma) * (1-ratio) + plasma + Z.air.temperature = (Z.air.temperature - heat) * (1-ratio) + heat + for (var/datum/gas/G in Z.air.trace_gases) + var/datum/gas/avgG = locate(G.type) in traceavg + if (avgG) + G.moles = (G.moles - avgG.moles)*(1-ratio) + avgG.moles + + for (var/zone/Z in Cluster) + ShareRequired = 0 + Z.air.update_values() + + + +//Iteratively get all connected zones +zone/proc/JoinCluster(var/list/Cluster) + for(var/zone/Z in connected_zones) + if (!(Z in Cluster)) + Cluster += Z + Cluster = Z.JoinCluster(Cluster) + return Cluster + + + proc/ShareRatio(datum/gas_mixture/A, datum/gas_mixture/B, ratio) //Shares a specific ratio of gas between mixtures using simple weighted averages. var