private IEnumerator BloodDryUp(MetaDataNode tile) { //Blood should take 3 mins to dry (TG STATION) yield return(WaitFor.Seconds(180)); tile.IsSlippery = false; var floorDecals = matrix.Get <FloorDecal>(tile.Position, isServer: true); foreach (var decal in floorDecals) { if (decal.isBlood) { decal.color = new Color(decal.color.r / 2, decal.color.g / 2, decal.color.b / 2, decal.color.a); decal.name = $"dried {decal.name}"; } } }
public MetaDataNode Get(Vector3Int localPosition, bool createIfNotExists = true) { localPosition.z = 0; //Z Positions are always on 0 if (nodes.ContainsKey(localPosition) == false) { if (createIfNotExists) { nodes[localPosition] = new MetaDataNode(localPosition, reactionManager, matrix); } else { return(MetaDataNode.None); } } return(nodes[localPosition]); }
private float DealDamageAt(float damage, AttackType attackType, Vector3Int cellPos, Vector3 worldPosition) { var basicTile = metaTileMap.GetTile(cellPos, Layer.LayerType) as BasicTile; if (basicTile == null) { return(0); } if (basicTile.indestructible) { return(0); } MetaDataNode data = metaDataLayer.Get(cellPos); return(AddDamage(damage, attackType, data, basicTile, worldPosition)); }
private void AddGrillDamage(int damage, MetaDataNode data, Vector3Int cellPos, Vector3 bulletHitTarget) { data.Damage += damage; //Make grills a little bit weaker (set to 60 hp): if (data.Damage >= 60) { tileChangeManager.RemoveTile(cellPos, LayerType.Grills); tileChangeManager.UpdateTile(cellPos, TileType.WindowDamaged, "GrillDestroyed"); SoundManager.PlayNetworkedAtPos("GrillHit", bulletHitTarget, 1f); //Spawn rods: SpawnRods(bulletHitTarget); data.ResetDamage(); } }
private void OnWillDestroyServer(DestructionInfo info) { var tileWorldPosition = gameObject.TileWorldPosition().To3Int(); //release all of our gases at once when destroyed MetaDataLayer metaDataLayer = MatrixManager.AtPoint(tileWorldPosition, true).MetaDataLayer; Vector3Int position = transform.localPosition.RoundToInt(); MetaDataNode node = metaDataLayer.Get(position, false); var shakeIntensity = (byte)Mathf.Lerp(byte.MinValue, byte.MaxValue / 2, GasMix.Pressure / MAX_EXPLOSION_EFFECT_PRESSURE); var shakeDistance = Mathf.Lerp(1, 64, GasMix.Pressure / MAX_EXPLOSION_EFFECT_PRESSURE); node.GasMix += GasMix; metaDataLayer.UpdateSystemsAt(position); ChatRelay.Instance.AddToChatLogServer(ChatEvent.Local($"{name} exploded!", gameObject.TileWorldPosition())); ItemFactory.SpawnMetal(2, tileWorldPosition.To2Int(), parent: transform.parent); ExplosionUtils.PlaySoundAndShake(tileWorldPosition, shakeIntensity, (int)shakeDistance); }
public override void UpdateAt(Vector3Int localPosition) { MetaDataNode node = metaDataLayer.Get(localPosition); MetaUtils.RemoveFromNeighbors(node); externalNodes.TryRemove(node, out MetaDataNode nothing); node.IsIsolatedNode = false; // If the node is atmos passable (i.e. space or room), we need to setup its neighbors again, otherwise it's occupied and does need a neighbor check if (metaTileMap.IsAtmosPassableAt(localPosition, true)) { node.ClearNeighbors(); node.Type = metaTileMap.IsSpaceAt(localPosition, true) ? NodeType.Space : NodeType.Room; if (node.Type == NodeType.Space) { node.ThermalConductivity = AtmosDefines.SPACE_THERMAL_CONDUCTIVITY; node.HeatCapacity = AtmosDefines.SPACE_HEAT_CAPACITY; } } else { node.Type = NodeType.Occupied; if (matrix.GetFirst <RegisterDoor>(localPosition, true)) { node.IsIsolatedNode = true; //TODO hard coded these values, might be better to put them in register door? node.ThermalConductivity = 0.001f; node.HeatCapacity = 10000f; } } if (node.IsIsolatedNode == false && node.Type != NodeType.Space && matrix.MetaTileMap.GetTile(localPosition, true) is BasicTile tile && tile != null) { node.HeatCapacity = tile.HeatCapacity; node.ThermalConductivity = tile.ThermalConductivity; } SetupNeighbors(node); MetaUtils.AddToNeighbors(node); }
/// <summary> /// Used to transfer heat between an Solid tile and Space /// Uses data from MetaDataNode for solid node and MetaDataNode date for Space node /// </summary> private void RadiateTemperatureToSpace(MetaDataNode currentNode, MetaDataNode openNode, float tempDelta) { if (currentNode.HeatCapacity <= 0) { return; } if (Mathf.Abs(tempDelta) <= AtmosDefines.MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) { return; } //The larger the combined capacity the less is shared var heat = openNode.ThermalConductivity * tempDelta * (currentNode.HeatCapacity * AtmosDefines.SPACE_HEAT_CAPACITY / (currentNode.HeatCapacity + AtmosDefines.SPACE_HEAT_CAPACITY)); currentNode.ConductivityTemperature -= heat / currentNode.HeatCapacity; }
/// <summary> /// Calculate the average Gas tile if you averaged all the adjacent ones and itself /// </summary> /// <returns>The mean gas mix.</returns> private void CalcMeanGasMix() { meanGasMix.Clear(); var targetCount = 0; for (var i = 0; i < nodes.Count; i++) { MetaDataNode node = nodes[i]; if (node == null) { continue; } //If node is not occupied then we want to add it to the total if (node.IsOccupied == false && node.IsIsolatedNode == false) { meanGasMix.Volume += node.GasMix.Volume; GasMix.TransferGas(meanGasMix, node.GasMix, node.GasMix.Moles, true); targetCount++; } else if (node.IsIsolatedNode == false) { //Remove all overlays for occupied tiles RemovalAllGasOverlays(node); //We trap the gas in the walls to stop instances where you remove a wall and theres a vacuum there } } // Sometimes, we calculate the meanGasMix of a tile surrounded by IsOccupied tiles (no atmos, ie: walls) if (targetCount == 0) { return; } meanGasMix.Volume /= targetCount; //Note: this assumes the volume of all tiles are the same foreach (var gasData in meanGasMix.GasesArray) { meanGasMix.GasData.SetMoles(gasData.GasSO, meanGasMix.GasData.GetGasMoles(gasData.GasSO) / targetCount); } }
public float EqualisePipe(MetaDataNode Node, ReagentMix Mix) { //add Radiation of Heat /* * float EnergyChange = 0f; //Minuses energy taken away, + is energy added to the pipe * if (Node.IsSpace) * { * //Radiation * //Invisible pipes to radiation * EnergyChange = -(StefanBoltzmannConstant * (Mix.InternalEnergy)); * Node.GasMix = GasMixes.Space; * } * * float EnergyTransfered = * ((390 * (Node.GasMix.Temperature -Mix.Temperature)) / 0.01f); * * float EqualiseTemperature = (Node.GasMix.InternalEnergy + Mix.InternalEnergy) / * (Node.GasMix.WholeHeatCapacity + Mix.WholeHeatCapacity); * * var ChangeInInternalEnergy = Mix.WholeHeatCapacity* (EqualiseTemperature -Mix.Temperature); * * if (Math.Abs( EnergyTransfered) > Math.Abs( ChangeInInternalEnergy)) * { * EnergyChange += ChangeInInternalEnergy; * } * else * { * EnergyChange += EnergyTransfered; * } * //Logger.Log("EnergyChange > " + EnergyChange); * var gas = Node.GasMix; * gas.InternalEnergy = gas.InternalEnergy + (-EnergyChange); * if (gas.InternalEnergy < 0) * { * Logger.LogWarning("OHHHH", Category.Atmos); * gas.InternalEnergy = 1; * } * Node.GasMix = gas; * return (EnergyChange); */ return(0); }
private void FindRoomAt(Vector3Int position) { if (!metaTileMap.IsAtmosPassableAt(position, true)) { MetaDataNode node = metaDataLayer.Get(position); node.Type = NodeType.Occupied; if (matrix.GetFirst <RegisterDoor>(position, true)) { node.IsClosedAirlock = true; } SetupNeighbors(node); } else if (!metaTileMap.IsSpaceAt(position, true) && !metaDataLayer.IsRoomAt(position) && !metaDataLayer.IsSpaceAt(position)) { CreateRoom(position); } }
/// <summary> /// The thing that actually equalises the tiles /// </summary> private void Equalize() { // If there is just one isolated tile, it's not nescessary to calculate the mean. Speeds up things a bit. if (nodes.Count > 1) { //Calculate the average gas from adding up all the adjacent tiles and dividing by the number of tiles GasMix MeanGasMix = CalcMeanGasMix(); for (var i = 0; i < nodes.Count; i++) { MetaDataNode node = nodes[i]; if (!node.IsOccupied) { node.GasMix = CalcAtmos(node.GasMix, MeanGasMix); } } } }
/// <summary> /// Calculate the average Gas tile if you averaged all the adjacent ones and itself /// </summary> /// <returns>The mean gas mix.</returns> private GasMix CalcMeanGasMix() { meanGasMix.Copy(GasMixes.Space); int targetCount = 0; for (var i = 0; i < nodes.Count; i++) { MetaDataNode node = nodes[i]; if (node.IsSpace) { //Set to 0 if space node.GasMix *= 0; } for (int j = 0; j < Gas.Count; j++) { meanGasMix.Gases[j] += node.GasMix.Gases[j]; } meanGasMix.Pressure += node.GasMix.Pressure; if (!node.IsOccupied) { targetCount++; } else { //Decay if occupied node.GasMix *= 0; } } for (int j = 0; j < Gas.Count; j++) { meanGasMix.Gases[j] /= targetCount; } meanGasMix.Pressure /= targetCount; return(meanGasMix); }
private void ServerDoCPR(GameObject performer, GameObject target, BodyPartType TargetBodyPart) { var health = target.GetComponent <LivingHealthMasterBase>(); Vector3Int position = health.ObjectBehaviour.AssumedWorldPositionServer(); MetaDataNode node = MatrixManager.GetMetaDataAt(position); bool hasLung = false; bool hasHeart = false; foreach (var BodyPart in health.GetBodyPartsInZone(TargetBodyPart, false)) { foreach (var organ in BodyPart.OrganList) { if (organ is Lungs lung) { lung.TryBreathing(node, 1); hasLung = true; } if (organ is Heart heart) { heart.Heartbeat(1); hasHeart = true; } } } if (hasHeart && hasLung) { Chat.AddActionMsgToChat( performer, $"You perform CPR on {targetName}.", $"{performerName} performs CPR on {targetName}."); Chat.AddExamineMsgFromServer(target, $"You feel fresh air enter your lungs. It feels good!"); } else { Chat.AddActionMsgToChat( performer, $"You perform CPR on {targetName}. It doesn't seem to work, maybe they're missing something.", $"{performerName} performs CPR on {targetName} In vain."); } }
private float AddDamage(float damage, AttackType attackType, MetaDataNode data, BasicTile basicTile, Vector3 worldPosition) { if (basicTile.indestructible) { return(0); } data.AddTileDamage(Layer.LayerType, basicTile.Armor.GetDamage(damage < basicTile.damageDeflection? 0: damage, attackType)); SoundManager.PlayNetworkedAtPos(basicTile.SoundOnHit, worldPosition); if (data.GetTileDamage(Layer.LayerType) >= basicTile.MaxHealth) { data.RemoveTileDamage(Layer.LayerType); tileChangeManager.RemoveTile(data.Position, Layer.LayerType); basicTile.LootOnDespawn?.SpawnLoot(worldPosition); } return(CalculateAbsorbDamaged(attackType, data, basicTile)); }
public override void UpdateAt(Vector3Int position) { MetaDataNode node = metaDataLayer.Get(position); MetaUtils.RemoveFromNeighbors(node); if (metaTileMap.IsAtmosPassableAt(position)) { node.ClearNeighbors(); node.Type = metaTileMap.IsSpaceAt(position) ? NodeType.Space : NodeType.Room; SetupNeighbors(node); MetaUtils.AddToNeighbors(node); } else { node.Type = NodeType.Occupied; } }
private void OnWillDestroyServer(DestructionInfo info) { var tileWorldPosition = gameObject.TileWorldPosition().To3Int(); //release all of our gases at once when destroyed MetaDataLayer metaDataLayer = MatrixManager.AtPoint(tileWorldPosition, true).MetaDataLayer; Vector3Int position = transform.localPosition.RoundToInt(); MetaDataNode node = metaDataLayer.Get(position, false); var shakeIntensity = (byte)Mathf.Lerp(byte.MinValue, byte.MaxValue / 2, GasMix.Pressure / MAX_EXPLOSION_EFFECT_PRESSURE); var shakeDistance = Mathf.Lerp(1, 64, GasMix.Pressure / MAX_EXPLOSION_EFFECT_PRESSURE); node.GasMix += GasMix; metaDataLayer.UpdateSystemsAt(position); Chat.AddLocalDestroyMsgToChat(gameObject.ExpensiveName(), " exploded!", gameObject.TileWorldPosition()); Spawn.ServerPrefab("Metal", gameObject.TileWorldPosition().To3Int(), transform.parent, count: 2, scatterRadius: Spawn.DefaultScatterRadius, cancelIfImpassable: true); ExplosionUtils.PlaySoundAndShake(tileWorldPosition, shakeIntensity, (int)shakeDistance); }
private void AssignType(IEnumerable <Vector3Int> positions, NodeType nodeType) { // Bulk assign type to nodes at given positions foreach (Vector3Int position in positions) { MetaDataNode node = metaDataLayer.Get(position); node.Type = nodeType; // assign room number, if type is room node.RoomNumber = nodeType == NodeType.Room ? roomCounter : -1; } // increase room counter, so next room will get a new number if (nodeType == NodeType.Room) { roomCounter++; } }
/// <summary> /// Calculate the average Gas tile if you averaged all the adjacent ones and itself /// </summary> /// <returns>The mean gas mix.</returns> private GasMix CalcMeanGasMix() { meanGasMix.Copy(GasMixes.Space); int targetCount = 0; for (var i = 0; i < nodes.Count; i++) { MetaDataNode node = nodes[i]; for (int j = 0; j < Gas.Count; j++) { meanGasMix.Gases[j] += node.GasMix.Gases[j]; } meanGasMix.Pressure += node.GasMix.Pressure; if (!node.IsOccupied) { targetCount++; } else { //Decay if occupied node.GasMix *= 0; } } // Sometime, we calculate the meanGasMix of a tile surrounded by IsOccupied tiles (no atmos) // This condition is to avoid a divide by zero error (or 0 / 0 that gives NaN) if (targetCount != 0) { for (int j = 0; j < Gas.Count; j++) { meanGasMix.Gases[j] /= targetCount; } meanGasMix.Pressure /= targetCount; } return(meanGasMix); }
public float EqualisePipe(MetaDataNode Node, ReagentMix Mix) { //add Radiation of Heat float EnergyChange = 0f; //Minuses energy taken away, + is energy added to the pipe if (Node.IsSpace) { //Radiation //Invisible pipes to radiation EnergyChange = -(StefanBoltzmannConstant * (Mix.InternalEnergy)); Node.GasMix = GasMixes.Space; } float EnergyTransfered = ((390 * (Node.GasMix.Temperature - Mix.Temperature)) / 0.01f); float EqualiseTemperature = (Node.GasMix.InternalEnergy + Mix.InternalEnergy) / (Node.GasMix.WholeHeatCapacity + Mix.WholeHeatCapacity); var ChangeInInternalEnergy = Mix.WholeHeatCapacity * (EqualiseTemperature - Mix.Temperature); if (Math.Abs(EnergyTransfered) > Math.Abs(ChangeInInternalEnergy)) { EnergyChange += ChangeInInternalEnergy; } else { EnergyChange += EnergyTransfered; } //Logger.Log("EnergyChange > " + EnergyChange); var gas = Node.GasMix; gas.InternalEnergy = gas.InternalEnergy + (-EnergyChange); if (gas.InternalEnergy < 0) { Logger.LogWarning("OHHHH", Category.Atmos); gas.InternalEnergy = 1; } Node.GasMix = gas; return(EnergyChange); }
/// <summary> /// Damage a window tile, incrementaly /// </summary> /// <param name="damage">The amount of damage the window received</param> /// <param name="data">The data about the current state of this window</param> /// <param name="cellPos">The position of the window tile</param> /// <param name="hitPos">Where exactly the bullet hit</param> /// <param name="attackType">The type of attack that did the damage</param> /// <returns>The remaining damage to apply to the tile if the window is broken, 0 otherwise.</returns> private float AddWindowDamage(float damage, MetaDataNode data, Vector3Int cellPos, Vector3 hitPos, AttackType attackType, bool spawnPieces = true) { data.Damage += REINFORCED_WINDOW_ARMOR.GetDamage(damage, attackType); if (data.Damage >= 20 && data.Damage < 50) { tileChangeManager.UpdateTile(cellPos, TileType.WindowDamaged, "crack01"); data.WindowDamage = WindowDamageLevel.Crack01; } if (data.Damage >= 50 && data.Damage < 75) { tileChangeManager.UpdateTile(cellPos, TileType.WindowDamaged, "crack02"); data.WindowDamage = WindowDamageLevel.Crack02; } if (data.Damage >= 75 && data.Damage < MAX_WINDOW_DAMAGE) { tileChangeManager.UpdateTile(cellPos, TileType.WindowDamaged, "crack03"); data.WindowDamage = WindowDamageLevel.Crack03; } if (data.Damage >= MAX_WINDOW_DAMAGE) { tileChangeManager.RemoveTile(cellPos, LayerType.Effects); tileChangeManager.RemoveTile(cellPos, LayerType.Windows); data.WindowDamage = WindowDamageLevel.Broken; //Spawn 3 glass shards with different sprites: if (spawnPieces) { SpawnGlassShards(hitPos); } //Play the breaking window sfx: SoundManager.PlayNetworkedAtPos("GlassBreak0#", hitPos, 1f); return(data.ResetDamage() - MAX_WINDOW_DAMAGE); } return(0); // The remaining damage after cracking the window. }
/// <summary> /// Gets the MetaDataNode from the Matrix at the given position. /// </summary> /// <param name="worldPosition">Position at which the node is looked for.</param> /// <returns>MetaDataNode at the position. If no Node that isn't space is found, MetaDataNode.Node will be returned.</returns> public static MetaDataNode GetMetaDataAt(Vector3Int worldPosition) { foreach (MatrixInfo mat in Instance.ActiveMatrices) { if (mat == null) { continue; } Vector3Int position = WorldToLocalInt(worldPosition, mat); MetaDataNode node = mat.MetaDataLayer.Get(position, false); if (node.Exists && node.IsSpace == false) { return(node); } } return(MetaDataNode.None); }
public void OnExposed(FireExposure exposure) { if (Layer.LayerType == LayerType.Floors || Layer.LayerType == LayerType.Base || Layer.LayerType == LayerType.Walls) { return; } var basicTile = metaTileMap.GetTile(exposure.ExposedLocalPosition, Layer.LayerType) as BasicTile; if (basicTile == null) { return; } MetaDataNode data = metaDataLayer.Get(exposure.ExposedLocalPosition); AddDamage(exposure.StandardDamage(), AttackType.Fire, data, basicTile, exposure.ExposedWorldPosition); }
//Handles checking for vfx changes //If needed, sends them to a queue in ReactionManager so that main thread will apply them private void GasVisualEffects(MetaDataNode node) { if (node.GasMix.GetMoles(Gas.Plasma) > 0.4) //If node has an almost combustible ammount of plasma { if (!fogTiles.Contains(node.Position)) //And if it hasn't already been identified as a tile that should have plasma fx { node.ReactionManager.AddFogEvent(node); //Add it to the atmos vfx queue in ReactionManager fogTiles.Add(node.Position); //Add it to fogTiles } } else //If there isn't 0.4 moles of plasma, remove the fx { if (fogTiles.Contains(node.Position) && (node.GasMix.GetMoles(Gas.Plasma) < 0.3)) { node.ReactionManager.RemoveFogEvent(node); fogTiles.Remove(node.Position); } } }
/// <summary> /// Damage a window tile, incrementaly /// </summary> /// <param name="damage">The amount of damage the window received</param> /// <param name="data">The data about the current state of this window</param> /// <param name="cellPos">The position of the window tile</param> /// <param name="hitPos">Where exactly the bullet hit</param> /// <param name="attackType">The type of attack that did the damage</param> /// <returns>The remaining damage to apply to the tile if the window is broken, 0 otherwise.</returns> private float AddWindowDamage(float damage, MetaDataNode data, Vector3Int cellPos, Vector3 hitPos, AttackType attackType, bool spawnPieces = true) { BasicTile tile = null; data.Damage += GetReducedDamage(cellPos, damage, attackType); if (data.Damage >= 20 && data.Damage < 50) { tileChangeManager.UpdateTile(cellPos, TileType.WindowDamaged, "crack01"); data.WindowDamage = WindowDamageLevel.Crack01; } if (data.Damage >= 50 && data.Damage < 75) { tileChangeManager.UpdateTile(cellPos, TileType.WindowDamaged, "crack02"); data.WindowDamage = WindowDamageLevel.Crack02; } if (data.Damage >= 75 && data.Damage < GetMaxDamage(cellPos)) { tileChangeManager.UpdateTile(cellPos, TileType.WindowDamaged, "crack03"); data.WindowDamage = WindowDamageLevel.Crack03; } if (data.Damage >= GetMaxDamage(cellPos)) { tile = tileChangeManager.RemoveTile(cellPos, LayerType.Windows) as BasicTile; data.WindowDamage = WindowDamageLevel.Broken; //Spawn up to 2 glass shards with different sprites: if (spawnPieces) { SpawnGlassShards(hitPos); } //Play the breaking window sfx: SoundManager.PlayNetworkedAtPos("GlassBreak0#", hitPos, 1f); } return(CalculateAbsorbDamaged(cellPos, attackType, data, tile)); }
//Handles checking for vfx changes //If needed, sends them to a queue in ReactionManager so that main thread will apply them private void GasVisualEffects(MetaDataNode node) { if (node == null || node.ReactionManager == null) { return; } foreach (var gasData in node.GasMix.GasesArray) { var gas = gasData.GasSO; if (!gas.HasOverlay) { continue; } var gasAmount = node.GasMix.GetMoles(gas); if (gasAmount > gas.MinMolesToSee) { if (node.GasOverlayData.Contains(gas)) { continue; } node.AddGasOverlay(gas); node.ReactionManager.TileChangeManager.AddOverlay(node.Position, TileManager.GetTile(TileType.Effects, gas.TileName) as OverlayTile); } else { if (node.GasOverlayData.Contains(gas) == false) { continue; } node.RemoveGasOverlay(gas); node.ReactionManager.TileChangeManager.RemoveOverlaysOfType(node.Position, LayerType.Effects, gas.OverlayType); } } }
private void Update() { timePassed += Time.deltaTime; if (timePassed < 0.5) { return; } timePassed = 0; foreach (MetaDataNode node in hotspots.Values.ToArray()) { if (node.Hotspot != null) { if (node.Hotspot.Process()) { if (node.Hotspot.Volume > 0.95 * node.GasMix.Volume && node.Hotspot.Temperature > Reactions.FIRE_MINIMUM_TEMPERATURE_TO_SPREAD) { for (var i = 0; i < node.Neighbors.Length; i++) { MetaDataNode neighbor = node.Neighbors[i]; if (neighbor != null) { ExposeHotspot(node.Neighbors[i].Position, node.GasMix.Temperature * 0.85f, node.GasMix.Volume / 4); } } } tileChangeManager.UpdateTile(node.Position, TileType.Effects, "Fire"); } else { node.Hotspot = null; hotspots.Remove(node.Position); tileChangeManager.RemoveTile(node.Position, LayerType.Effects); } } } }
/// <summary> /// Calculate the average Gas tile if you averaged all the adjacent ones and itself /// </summary> /// <returns>The mean gas mix.</returns> private void CalcMeanGasMix() { meanGasMix.Copy(GasMixes.Empty); var targetCount = 0; for (var i = 0; i < nodes.Count; i++) { MetaDataNode node = nodes[i]; if (node == null) { continue; } meanGasMix.Volume += node.GasMix.Volume; GasMix.TransferGas(meanGasMix, node.GasMix, node.GasMix.Moles); if (!node.IsOccupied) { targetCount++; } else { //Decay if occupied node.GasMix.SetToEmpty(); } } // Sometimes, we calculate the meanGasMix of a tile surrounded by IsOccupied tiles (no atmos, ie: walls) if (targetCount == 0) { return; } meanGasMix.Volume /= targetCount; //Note: this assumes the volume of all tiles are the same for (var i = 0; i < Gas.Count; i++) { meanGasMix.Gases[i] = meanGasMix.Gases[i] / targetCount; } }
public void React(GasMix gasMix, MetaDataNode node) { var waterMoles = gasMix.GetMoles(Gas.WaterVapor); if (waterMoles != 0 && waterMoles / gasMix.Moles > 0.1) { //No reaction return; } var cleanedAir = Mathf.Min( gasMix.GetMoles(Gas.Miasma), 20 + (gasMix.Temperature - AtmosDefines.FIRE_MINIMUM_TEMPERATURE_TO_EXIST - 70) / 20); gasMix.RemoveGas(Gas.Miasma, cleanedAir); gasMix.AddGas(Gas.Oxygen, cleanedAir); gasMix.SetTemperature(gasMix.Temperature + cleanedAir * 0.002f); }
private void CollectorUpdate() { if (CustomNetworkManager.IsServer == false) { return; } MetaDataNode node = registerTile.Matrix.GetMetaDataNode(registerTile.LocalPositionServer); if (node == null) { radiationLevel = 0; moduleSupplyingDevice.ProducingWatts = 0; return; } radiationLevel = node.RadiationNode.RadiationLevel; generatedWatts = radiationLevel * radiationWatts; moduleSupplyingDevice.ProducingWatts = generatedWatts; }
public void ExposeHotspot(Vector3Int position, float temperature, float volume) { if (hotspots.ContainsKey(position) && hotspots[position].Hotspot != null) { // TODO soh? hotspots[position].Hotspot.UpdateValues(volume * 25, temperature); } else { MetaDataNode node = metaDataLayer.Get(position); GasMix gasMix = node.Atmos; if (gasMix.GetMoles(Gas.Plasma) > 0.5 && gasMix.GetMoles(Gas.Oxygen) > 0.5 && temperature > Reactions.PLASMA_MINIMUM_BURN_TEMPERATURE) { // igniting Hotspot hotspot = new Hotspot(node, temperature, volume * 25); node.Hotspot = hotspot; hotspots[position] = node; } } }
public virtual Value evaluate(Context cx, MetaDataNode node) { output("<MetaDataNode id=\"" + node.id + "\">"); indent_Renamed_Field++; if (node.data != null) { MetaDataEvaluator mde = new MetaDataEvaluator(); node.evaluate(cx, mde); } indent_Renamed_Field--; output("</MetaDataNode>"); return null; }