コード例 #1
0
    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.GasMix;

            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;
            }
        }

        if (hotspots.ContainsKey(position) && hotspots[position].Hotspot != null)
        {
            List <LivingHealthBehaviour> healths = matrix.Get <LivingHealthBehaviour>(position);

            foreach (LivingHealthBehaviour health in healths)
            {
                health.ApplyDamage(null, 1, DamageType.Burn);
            }
        }
    }
コード例 #2
0
    private float HandleBreathing(GasMix breathGasMix)
    {
        float oxygenPressure = breathGasMix.GetPressure(Gas.Oxygen);

        float oxygenUsed = 0;

        if (oxygenPressure < OXYGEN_SAFE_MIN)
        {
            if (Random.value < 0.2)
            {
                PostToChatMessage.Send("gasp", ChatChannel.Local);
            }

            if (oxygenPressure > 0)
            {
                float ratio = 1 - oxygenPressure / OXYGEN_SAFE_MIN;

                ApplyDamage(Mathf.Min(5 * ratio, 3), DamageType.Oxy);
                bloodSystem.OxygenLevel += 30 * ratio;

                oxygenUsed = breathGasMix.GetMoles(Gas.Oxygen) * ratio;
            }
            else
            {
                ApplyDamage(3, DamageType.Oxy);
            }
        }
        else
        {
            oxygenUsed = breathGasMix.GetMoles(Gas.Oxygen);
            bloodSystem.OxygenLevel += 30;
        }

        return(oxygenUsed);
    }
コード例 #3
0
    private float HandleBreathing(GasMix breathGasMix)
    {
        float oxygenPressure = breathGasMix.GetPressure(Gas.Oxygen);

        float oxygenUsed = 0;

        if (oxygenPressure < OXYGEN_SAFE_MIN)
        {
            if (Random.value < 0.1)
            {
                Chat.AddActionMsgToChat(gameObject, "You gasp for breath", $"{gameObject.name} gasps");
            }

            if (oxygenPressure > 0)
            {
                float ratio = 1 - oxygenPressure / OXYGEN_SAFE_MIN;
                bloodSystem.OxygenDamage += 1 * ratio;
                oxygenUsed = breathGasMix.GetMoles(Gas.Oxygen) * ratio;
            }
            else
            {
                bloodSystem.OxygenDamage += 1;
            }
            IsSuffocating = true;
        }
        else
        {
            oxygenUsed                = breathGasMix.GetMoles(Gas.Oxygen);
            IsSuffocating             = false;
            bloodSystem.OxygenDamage -= 2.5f;
            breatheCooldown           = 4;
        }
        return(oxygenUsed);
    }
コード例 #4
0
    private float HandleBreathing(GasMix breathGasMix)
    {
        float oxygenPressure = breathGasMix.GetPressure(Gas.Oxygen);

        float oxygenUsed = 0;

        if (oxygenPressure < OXYGEN_SAFE_MIN)
        {
            if (Random.value < 0.1)
            {
                PostToChatMessage.SendGasp(base.gameObject);
            }

            if (oxygenPressure > 0)
            {
                float ratio = 1 - oxygenPressure / OXYGEN_SAFE_MIN;
                bloodSystem.OxygenDamage += 1 * ratio;
                oxygenUsed = breathGasMix.GetMoles(Gas.Oxygen) * ratio;
            }
            else
            {
                bloodSystem.OxygenDamage += 1;
            }
            IsSuffocating = true;
        }
        else
        {
            oxygenUsed                = breathGasMix.GetMoles(Gas.Oxygen);
            IsSuffocating             = false;
            bloodSystem.OxygenDamage -= 2.5f;
            breatheCooldown           = 4;
        }
        return(oxygenUsed);
    }
コード例 #5
0
    public void ExposeHotspot(Vector3Int localPosition, float temperature, float volume)
    {
        if (hotspots.ContainsKey(localPosition) && hotspots[localPosition].Hotspot != null)
        {
            // TODO soh?
            hotspots[localPosition].Hotspot.UpdateValues(volume * 25, temperature);
        }
        else
        {
            MetaDataNode node   = metaDataLayer.Get(localPosition);
            GasMix       gasMix = node.GasMix;

            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[localPosition] = node;
            }
        }

        if (hotspots.ContainsKey(localPosition) && hotspots[localPosition].Hotspot != null)
        {
            //expose everything on this tile
            Expose(localPosition, localPosition);

            //expose impassable things on the adjacent tile
            Expose(localPosition, localPosition + Vector3Int.right);
            Expose(localPosition, localPosition + Vector3Int.left);
            Expose(localPosition, localPosition + Vector3Int.up);
            Expose(localPosition, localPosition + Vector3Int.down);
        }
    }
コード例 #6
0
    public void ExposeHotspot(Vector3Int localPosition, float temperature, float volume)
    {
        if (hotspots.ContainsKey(localPosition) && hotspots[localPosition].Hotspot != null)
        {
            // TODO soh?
            hotspots[localPosition].Hotspot.UpdateValues(volume * 25, temperature);
        }
        else
        {
            Profiler.BeginSample("MarkForAddition");
            MetaDataNode node   = metaDataLayer.Get(localPosition);
            GasMix       gasMix = node.GasMix;

            if (gasMix.GetMoles(Gas.Plasma) > 0.5 && gasMix.GetMoles(Gas.Oxygen) > 0.5 && temperature > Reactions.PlasmaMaintainFire)
            {
                // igniting
                //addition will be done later in Update
                hotspotsToAdd.Add(new Hotspot(node, temperature, volume * 25));
            }
            Profiler.EndSample();
        }

        if (hotspots.ContainsKey(localPosition) && hotspots[localPosition].Hotspot != null)
        {
            //expose everything on this tile
            Expose(localPosition, localPosition);

            //expose impassable things on the adjacent tile
            Expose(localPosition, localPosition + Vector3Int.right);
            Expose(localPosition, localPosition + Vector3Int.left);
            Expose(localPosition, localPosition + Vector3Int.up);
            Expose(localPosition, localPosition + Vector3Int.down);
        }
    }
コード例 #7
0
    /// <summary>
    /// Placeholder method to add some effects for breathing plasma. Eventually this behavior should be
    /// handled with interfaces we can implement so different species react differently.
    /// </summary>
    /// <param name="plasmaAmount"></param>
    private float HandleBreathingPlasma(GasMix gasMix)
    {
        float plasmaPressure = gasMix.GetPressure(Gas.Plasma);

        float plasmaConsumed = 0;

        plasmaConsumed = gasMix.GetMoles(Gas.Plasma) * AtmosConstants.BREATH_VOLUME;
        // there is some plasma in the ambient but it is still safe
        if (plasmaPressure <= PLASMA_SAFE_MAX && plasmaPressure > PLASMA_WARNING_LEVEL)
        {
            if (DMMath.Prob(90))
            {
                return(plasmaConsumed);
            }

            // 10% chances of message
            var theirPronoun = gameObject.Player() != null
                                ? gameObject.Player().Script.characterSettings.TheirPronoun(gameObject.Player().Script)
                                : "its";

            Chat.AddActionMsgToChat(
                gameObject,
                plasmaLowYouMessages.PickRandom(),
                string.Format(
                    plasmaLowOthersMessages.PickRandom(),
                    gameObject.ExpensiveName(),
                    string.Format(plasmaLowOthersMessages.PickRandom(), gameObject.ExpensiveName(), theirPronoun))
                );
        }
        // enough plasma to be visible and damage us!
        else if (plasmaPressure > PLASMA_SAFE_MAX)
        {
            var plasmaDamage = (gasMix.GetMoles(Gas.Plasma) / PLASMA_SAFE_MAX) * 10;
            bloodSystem.ToxinLevel = Mathf.Clamp(bloodSystem.ToxinLevel + Mathf.Clamp(plasmaDamage, MIN_TOXIN_DMG, MAX_TOXIN_DMG), 0, 200);

            if (DMMath.Prob(90))
            {
                return(plasmaConsumed);
            }

            // 10% chances of message
            var theirPronoun = gameObject.Player() != null
                                ? gameObject.Player().Script.characterSettings.TheirPronoun(gameObject.Player().Script)
                                : "its";

            Chat.AddActionMsgToChat(
                gameObject,
                plasmaHighYouMessages.PickRandom(),
                string.Format(plasmaHighOthersMessages.PickRandom(), gameObject.ExpensiveName(), theirPronoun)
                );
        }
        return(plasmaConsumed);
    }
コード例 #8
0
        public void React(GasMix gasMix, MetaDataNode node)
        {
            var oxyMoles = gasMix.GetMoles(Gas.Oxygen);

            gasMix.AddGas(Gas.Plasma, oxyMoles);
            gasMix.RemoveGas(Gas.Oxygen, oxyMoles);
        }
コード例 #9
0
        public void React(GasMix gasMix, Vector3 tilePos, Matrix matrix)
        {
            var oxyMoles = gasMix.GetMoles(Gas.Oxygen);

            gasMix.AddGas(Gas.Plasma, oxyMoles);
            gasMix.RemoveGas(Gas.Oxygen, oxyMoles);
        }
コード例 #10
0
    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;
            }
        }
    }
コード例 #11
0
    private float HandleBreathing(GasMix gasMix)
    {
        float oxygenPressure = gasMix.GetPressure(Gas.Oxygen);
        float plasmaAmount   = gasMix.GetMoles(Gas.Plasma);

        float oxygenUsed = 0;

        if (plasmaAmount > 0)
        {
            HandleBreathingPlasma(plasmaAmount);
        }

        if (oxygenPressure < OXYGEN_SAFE_MIN)
        {
            if (Random.value < 0.1)
            {
                Chat.AddActionMsgToChat(gameObject, "You gasp for breath", $"{gameObject.ExpensiveName()} gasps");
            }

            if (oxygenPressure > 0)
            {
                float ratio = 1 - oxygenPressure / OXYGEN_SAFE_MIN;
                bloodSystem.OxygenDamage += 1 * ratio;
                oxygenUsed = gasMix.GetMoles(Gas.Oxygen) * ratio * AtmosConstants.BREATH_VOLUME;
            }
            else
            {
                bloodSystem.OxygenDamage += 1;
            }
            IsSuffocating = true;
        }
        else
        {
            oxygenUsed                = gasMix.GetMoles(Gas.Oxygen) * AtmosConstants.BREATH_VOLUME;
            IsSuffocating             = false;
            bloodSystem.OxygenDamage -= 2.5f;
            breatheCooldown           = 4;
        }
        return(oxygenUsed);
    }
コード例 #12
0
    /// <summary>
    /// Pulls in the desired gas, as well as others, from the specified gas mix and adds them to the blood stream
    /// </summary>
    /// <param name="gasMix">The gas mix to breathe in from</param>
    /// <param name="blood">The blood to put gases into</param>
    /// <returns> True if breathGasMix was changed </returns>
    private bool BreatheIn(GasMix breathGasMix, ReagentMix blood, float efficiency)
    {
        if (RelatedPart.HealthMaster.RespiratorySystem.CanBreathAnywhere)
        {
            blood.Add(RelatedPart.requiredReagent, RelatedPart.bloodType.GetSpareGasCapacity(blood));
            return(false);
        }

        ReagentMix toInhale   = new ReagentMix();
        var        Available  = RelatedPart.bloodType.GetGasCapacityOfnonMeanCarrier(blood);
        var        TotalMoles = breathGasMix.Moles;

        ToxinBreathinCheck(breathGasMix);
        foreach (var gasValues in breathGasMix.GasData.GasesArray)
        {
            var gas = gasValues.GasSO;
            if (GAS2ReagentSingleton.Instance.DictionaryGasToReagent.ContainsKey(gas) == false)
            {
                continue;
            }

            // n = PV/RT
            float gasMoles = breathGasMix.GetMoles(gas);

            // Get as much as we need, or as much as in the lungs, whichever is lower
            Reagent gasReagent    = GAS2ReagentSingleton.Instance.GetGasToReagent(gas);
            float   molesRecieved = 0;
            if (gasReagent == RelatedPart.bloodType.CirculatedReagent)
            {
                molesRecieved = Mathf.Min(gasMoles, RelatedPart.bloodType.GetSpareGasCapacity(blood, gasReagent));
            }
            else
            {
                if (gasMoles == 0)
                {
                    molesRecieved = 0;
                }
                else
                {
                    molesRecieved = Available / (TotalMoles / gasMoles);
                    molesRecieved = Mathf.Min(molesRecieved, gasMoles);
                }
            }

            if (molesRecieved > 0)
            {
                toInhale.Add(gasReagent, molesRecieved * efficiency);
            }

            //TODO: Add pressureSafeMax check here, for hyperoxia
        }

        RelatedPart.HealthMaster.RespiratorySystem.GasExchangeToBlood(breathGasMix, blood, toInhale);

        // Counterintuitively, in humans respiration is stimulated by pressence of CO2 in the blood, not lack of oxygen
        // May want to change this code to reflect that in the future so people don't hyperventilate when they are on nitrous oxide
        var   inGas           = GAS2ReagentSingleton.Instance.GetGasToReagent(requiredGas);
        float bloodCap        = RelatedPart.bloodType.GetGasCapacity(RelatedPart.BloodContainer.CurrentReagentMix);
        float foreignCap      = RelatedPart.bloodType.GetGasCapacityForeign(RelatedPart.BloodContainer.CurrentReagentMix);
        float bloodSaturation = 0;

        if (bloodCap + foreignCap == 0)
        {
            bloodSaturation = 0;
        }
        else
        {
            var ratioNativeBlood = bloodCap / (bloodCap + foreignCap);
            bloodSaturation = RelatedPart.BloodContainer[RelatedPart.requiredReagent] * ratioNativeBlood / bloodCap;
        }

        if (bloodSaturation >= RelatedPart.HealthMaster.CirculatorySystem.BloodInfo.BLOOD_REAGENT_SATURATION_OKAY)
        {
            currentBreatheCooldown = breatheCooldown;             //Slow breathing, we're all good
            RelatedPart.HealthMaster.HealthStateController.SetSuffocating(false);
        }
        else if (bloodSaturation <= RelatedPart.HealthMaster.CirculatorySystem.BloodInfo.BLOOD_REAGENT_SATURATION_BAD)
        {
            RelatedPart.HealthMaster.HealthStateController.SetSuffocating(true);
            if (Random.value < 0.2)
            {
                Chat.AddActionMsgToChat(RelatedPart.HealthMaster.gameObject, "You gasp for breath",
                                        $"{RelatedPart.HealthMaster.playerScript.visibleName} gasps");
            }
        }

        //Debug.Log("Gas inhaled: " + toInhale.Total + " Saturation: " + saturation);
        return(toInhale.Total > 0);
    }
コード例 #13
0
    private bool HandleWearingGasMask(GasMix gasMix)
    {
        bool filtered = false;

        // if there is too much CO2 in the air
        if (gasMix.GetMoles(Gas.CarbonDioxide) >= 30)
        {
            GasMix gasMix2 = gasMix;
            gasMix2.RemoveGas(Gas.CarbonDioxide, 30);
            HandleBreathingCarbonDioxide(gasMix2);
            filtered = true;
        }
        // if there is too much plasma in the air
        if (gasMix.GetMoles(Gas.Plasma) >= 25)
        {
            GasMix gasMix2 = gasMix;
            gasMix2.RemoveGas(Gas.Plasma, 25);
            float plasmaBreathedWithMask = HandleBreathingPlasma(gasMix2);
            if (plasmaBreathedWithMask > 0)
            {
                gasMix.RemoveGas(Gas.Plasma, plasmaBreathedWithMask);
                registerTile.Matrix.MetaDataLayer.UpdateSystemsAt(registerTile.LocalPositionClient, SystemType.AtmosSystem);
            }
            filtered = true;
        }

        //if there's not enough to cause the plasma or CO2 warnings, skip the breathe messages
        if ((gasMix.GetMoles(Gas.Plasma) < PLASMA_WARNING_LEVEL && gasMix.GetMoles(Gas.Plasma) > 0) || (gasMix.GetMoles(Gas.CarbonDioxide) < CARBON_DIOXIDE_WARNING_LEVEL && gasMix.GetMoles(Gas.CarbonDioxide) > 0))
        {
            return(true);
        }

        //if somehow both are 0 return false
        if (gasMix.GetMoles(Gas.Plasma) == 0 && gasMix.GetMoles(Gas.CarbonDioxide) == 0)
        {
            return(false);
        }

        if (DMMath.Prob(90))
        {
            return(true);
        }

        if (!filtered)
        {
            // 10% chance of message
            var theirPronoun = gameObject.Player() != null
                                ? gameObject.Player().Script.characterSettings.TheirPronoun(gameObject.Player().Script)
                                : "its";

            Chat.AddActionMsgToChat(
                gameObject,
                GasMaskFiltered.PickRandom(),
                string.Format(
                    GasMaskFilteredOthers.PickRandom(),
                    gameObject.ExpensiveName(),
                    string.Format(plasmaLowOthersMessages.PickRandom(), gameObject.ExpensiveName(), theirPronoun))
                );
            return(true);
        }
        return(false);
    }
コード例 #14
0
        /// <summary>
        /// Pulls in the desired gas, as well as others, from the specified gas mix and adds them to the blood stream
        /// </summary>
        /// <param name="gasMix">The gas mix to breathe in from</param>
        /// <param name="blood">The blood to put gases into</param>
        /// <returns> True if breathGasMix was changed </returns>
        private bool BreatheIn(GasMix breathGasMix, ReagentMix blood, float efficiency)
        {
            if (RelatedPart.HealthMaster.RespiratorySystem.CanBreatheAnywhere)
            {
                blood.Add(RelatedPart.requiredReagent, RelatedPart.bloodType.GetSpareGasCapacity(blood));
                return(false);
            }

            ReagentMix toInhale  = new ReagentMix();
            var        Available = RelatedPart.bloodType.GetNormalGasCapacity(blood);

            ToxinBreathinCheck(breathGasMix);
            float PercentageCanTake = 1;

            if (breathGasMix.Moles != 0)
            {
                PercentageCanTake = LungSize / breathGasMix.Moles;
            }

            if (PercentageCanTake > 1)
            {
                PercentageCanTake = 1;
            }

            var PressureMultiplier = breathGasMix.Pressure / pressureSafeMin;

            if (PressureMultiplier > 1)
            {
                PressureMultiplier = 1;
            }

            var TotalMoles = breathGasMix.Moles * PercentageCanTake;


            lock (breathGasMix.GasData.GasesArray)             //no Double lock
            {
                foreach (var gasValues in breathGasMix.GasData.GasesArray)
                {
                    var gas = gasValues.GasSO;
                    if (Gas.GasToReagent.TryGetValue(gas, out var gasReagent) == false)
                    {
                        continue;
                    }

                    // n = PV/RT
                    float gasMoles = breathGasMix.GetMoles(gas) * PercentageCanTake;

                    // Get as much as we need, or as much as in the lungs, whichever is lower
                    float molesRecieved = 0;

                    if (gasReagent == RelatedPart.bloodType.CirculatedReagent)
                    {
                        var PercentageMultiplier = (gasMoles / (TotalMoles));
                        molesRecieved = RelatedPart.bloodType.GetSpecialGasCapacity(blood) * PercentageMultiplier *
                                        PressureMultiplier;
                    }
                    else if (gasMoles != 0)
                    {
                        molesRecieved = (Available * (gasMoles / TotalMoles)) * PressureMultiplier;
                    }

                    if (molesRecieved > 0)
                    {
                        toInhale.Add(gasReagent, molesRecieved);
                    }
                }
            }

            RelatedPart.HealthMaster.RespiratorySystem.GasExchangeToBlood(breathGasMix, blood, toInhale, LungSize);


            // Counterintuitively, in humans respiration is stimulated by pressence of CO2 in the blood, not lack of oxygen
            // May want to change this code to reflect that in the future so people don't hyperventilate when they are on nitrous oxide
            float bloodCap        = RelatedPart.bloodType.GetNormalGasCapacity(RelatedPart.BloodContainer.CurrentReagentMix);
            var   bloodSaturation = 0f;

            if (bloodCap > 0)
            {
                bloodSaturation = RelatedPart.BloodContainer[RelatedPart.requiredReagent] / bloodCap;
            }

            if (bloodSaturation >= RelatedPart.HealthMaster.CirculatorySystem.BloodInfo.BLOOD_REAGENT_SATURATION_OKAY)
            {
                currentBreatheCooldown = breatheCooldown;                 //Slow breathing, we're all good
                RelatedPart.HealthMaster.HealthStateController.SetSuffocating(false);
            }
            else if (bloodSaturation <= RelatedPart.HealthMaster.CirculatorySystem.BloodInfo.BLOOD_REAGENT_SATURATION_BAD)
            {
                RelatedPart.HealthMaster.HealthStateController.SetSuffocating(true);
                if (DMMath.Prob(20))
                {
                    Chat.AddActionMsgToChat(RelatedPart.HealthMaster.gameObject, "You gasp for breath!",
                                            $"{RelatedPart.HealthMaster.playerScript.visibleName} gasps!");
                }
            }

            //Debug.Log("Gas inhaled: " + toInhale.Total + " Saturation: " + saturation);
            return(toInhale.Total > 0);
        }