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);
    }
    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);
    }
Beispiel #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)
            {
                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);
    }
Beispiel #4
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);
    }
Beispiel #5
0
    /// <summary>
    /// Expels unwanted gases from the blood stream into the given gas mix
    /// </summary>
    /// <param name="gasMix">The gas mix to breathe out into</param>
    /// <param name="blood">The blood to pull gases from</param>
    /// <returns> True if breathGasMix was changed </returns>
    private bool BreatheOut(GasMix gasMix, ReagentMix blood, float efficiency)
    {
        // This isn't exactly realistic, should also factor concentration of gases in the gasMix
        ReagentMix toExhale = new ReagentMix();

        foreach (var Reagent in blood.reagents.m_dict)
        {
            if (GAS2ReagentSingleton.Instance.DictionaryReagentToGas.ContainsKey(Reagent.Key))
            {
                // Try to prevent lungs removing desired gases and non gases from blood.
                // May want to add other gases that the lungs are unable to remove as well (ie toxins)
                var gas = GAS2ReagentSingleton.Instance.GetReagentToGas(Reagent.Key);
                if (gas != requiredGas && Reagent.Value > 0)
                {
                    toExhale.Add(Reagent.Key, Reagent.Value * efficiency);
                }
                else if (gas == requiredGas && Reagent.Value > 0)
                {
                    float ratio;
                    if (gasMix.GetPressure(requiredGas) < pressureSafeMin)
                    {
                        ratio = 1 - gasMix.GetPressure(requiredGas) / pressureSafeMin;
                    }
                    else
                    {
                        // Will still lose required gas suspended in blood plasma
                        ratio = RelatedPart.bloodType.BloodGasCapability / RelatedPart.bloodType.BloodCapacityOf;
                    }

                    toExhale.Add(Reagent.Key, ratio * Reagent.Value * efficiency);
                }
            }
        }

        RelatedPart.HealthMaster.RespiratorySystem.GasExchangeFromBlood(gasMix, blood, toExhale);
        //Debug.Log("Gas exhaled: " + toExhale.Total);
        return(toExhale.Total > 0);
    }
Beispiel #6
0
 /// <summary>
 /// Checks for toxic gases and if they excede their maximum range before they become deadly
 /// </summary>
 /// <param name="gasMix">the gases the character is breathing in</param>
 public virtual void ToxinBreathinCheck(GasMix gasMix)
 {
     if (RelatedPart.HealthMaster.RespiratorySystem.CanBreatheAnywhere ||
         RelatedPart.HealthMaster.playerScript == null) return;
     foreach (ToxicGas gas in toxicGases)
     {
         float pressure = gasMix.GetPressure(gas.GasType);
         if (pressure >= gas.PressureSafeMax)
         {
             RelatedPart.HealthMaster.RespiratorySystem.ApplyDamage(gas.UnsafeLevelDamage,
                 gas.UnsafeLevelDamageType);
         }
     }
 }
Beispiel #7
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 (healthMaster.RespiratorySystem.CanBreathAnywhere)
        {
            blood.Add(requiredReagent, bloodType.GetSpareGasCapacity(blood));
            return(false);
        }
        ReagentMix toInhale = new ReagentMix();

        for (int i = 0; i < breathGasMix.Gases.Length; i++)
        {
            if (GAS2ReagentSingleton.Instance.DictionaryGasToReagent.ContainsKey(Gas.All[i]))
            {
                // n = PV/RT
                float gasMoles = breathGasMix.GetPressure(Gas.All[i]) * LungSize / 8.314f / breathGasMix.Temperature;

                // Get as much as we need, or as much as in the lungs, whichever is lower
                Reagent gasReagent    = GAS2ReagentSingleton.Instance.GetGasToReagent(Gas.All[i]);
                float   molesRecieved = Mathf.Min(gasMoles, bloodType.GetSpareGasCapacity(blood, gasReagent));
                toInhale.Add(gasReagent, molesRecieved * efficiency);

                //TODO: Add pressureSafeMax check here, for hyperoxia
            }
        }
        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);
        var saturation = (toInhale[inGas] + blood[inGas]) / bloodType.GetGasCapacity(blood);

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

        //Debug.Log("Gas inhaled: " + toInhale.Total + " Saturation: " + saturation);
        return(toInhale.Total > 0);
    }
Beispiel #8
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);
    }
Beispiel #9
0
        private IEnumerator Breathe()
        {
            while (!health.IsDead)
            {
                MetaDataLayer metaDataLayer = MatrixManager.AtPoint(Vector3Int.RoundToInt(transform.position)).MetaDataLayer;

                GasMix atmos           = metaDataLayer.Get(transform.localPosition.RoundToInt(), false).Atmos;
                float  partialPressure = atmos.GetPressure(Gas.Oxygen);

                if (partialPressure < AtmosConstants.MINIMUM_OXYGEN_PRESSURE)
                {
                    float ratio = 1 - partialPressure / AtmosConstants.MINIMUM_OXYGEN_PRESSURE;
                    Logger.Log("URGENT TODO: Move this to LivingHealthBehaviour Respiratory system ", Category.Health);
                    //health.ApplyDamage(null, Mathf.Min(5 * ratio, 3), DamageType.Oxy);
                }
                else
                {
                    // TODO implement breathing (remove oxygen, add co2, etc.)
                }

                yield return(new WaitForSeconds(breathTime));
            }
        }
Beispiel #10
0
    private bool HandleBreathingCarbonDioxide(GasMix gasMix)
    {
        float carbonPressure = gasMix.GetPressure(Gas.CarbonDioxide);

        // there is a little carbon dioxide in the air.
        if (carbonPressure <= CARBON_DIOXIDE_SAFE_MAX && carbonPressure > CARBON_DIOXIDE_WARNING_LEVEL)
        {
            if (DMMath.Prob(90))
            {
                return(true);
            }

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

            Chat.AddActionMsgToChat(
                gameObject,
                CO2LowYouMessages.PickRandom(),
                string.Format(
                    CO2LowOthersMessages.PickRandom(),
                    gameObject.ExpensiveName(),
                    string.Format(plasmaLowOthersMessages.PickRandom(), gameObject.ExpensiveName(), theirPronoun))
                );
        }
        // enough carbon dioxide to start suffocating you!
        else if (carbonPressure > CARBON_DIOXIDE_SAFE_MAX)
        {
            if (CarbonSuffocationTimer >= 0)
            {
                CarbonSuffocationTimer++;
            }
            if (CarbonSuffocationTimer >= 3 && CarbonSuffocationTimer < 7)
            {
                IsSuffocating             = true;
                bloodSystem.OxygenDamage += 3;

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

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

                Chat.AddActionMsgToChat(
                    gameObject,
                    CO2MedYouMessages.PickRandom(),
                    string.Format(CO2MedOthersMessages.PickRandom(), gameObject.ExpensiveName(), theirPronoun)
                    );
            }
            else if (CarbonSuffocationTimer >= 7)
            {
                IsSuffocating             = true;
                bloodSystem.OxygenDamage += 8;

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

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

                Chat.AddActionMsgToChat(
                    gameObject,
                    CO2HighYouMessages.PickRandom(),
                    string.Format(CO2HighOthersMessages.PickRandom(), gameObject.ExpensiveName(), theirPronoun)
                    );
                return(true);
            }
        }

        if (carbonPressure < CARBON_DIOXIDE_WARNING_LEVEL)
        {
            CarbonSuffocationTimer = 0;
            return(carbonPressure > 0);
        }
        return(false);
    }
Beispiel #11
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;

        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.GetPressure(gas) * LungSize / (8.314f * breathGasMix.Temperature);

            // 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.Approx(0) == false)
            {
                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.PlayerScriptOwner.visibleName} gasps");
            }
        }

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