Example #1
0
        private void UpdateOxygen()
        {
            // Try to find grids that might contain oxygen
            var entities = new List <MyEntity>();
            var aabb     = Character.PositionComp.WorldAABB;

            MyGamePruningStructure.GetAllTopMostEntitiesInBox(ref aabb, entities);
            bool lowOxygenDamage = MySession.Static.Settings.EnableOxygen;
            bool noOxygenDamage  = MySession.Static.Settings.EnableOxygen;
            bool isInEnvironment = true;

            EnvironmentOxygenLevel = MyOxygenProviderSystem.GetOxygenInPoint(Character.PositionComp.GetPosition());

            bool oxygenReplenished = false;

            if (Sync.IsServer)
            {
                if (MySession.Static.Settings.EnableOxygen)
                {
                    float oxygenInput = CharacterGasSink.CurrentInputByType(OxygenId);
                    if (oxygenInput > 0 && !Definition.NeedsOxygen)
                    {
                        var oxygenInputPer100Frames = oxygenInput * 100f / MyEngineConstants.UPDATE_STEPS_PER_SECOND;
                        SuitOxygenAmount += oxygenInputPer100Frames;

                        if (oxygenInputPer100Frames >= Definition.OxygenConsumption)
                        {
                            oxygenReplenished = true;
                            noOxygenDamage    = false;
                            lowOxygenDamage   = false;
                        }
                    }
                }

                foreach (GasData gasInfo in m_storedGases)
                {
                    float gasInputPer100Frames  = Math.Min(gasInfo.Throughput, CharacterGasSink.CurrentInputByType(gasInfo.Id)) * 100f / MyEngineConstants.UPDATE_STEPS_PER_SECOND;
                    float gasOutputPer100Frames = Math.Min(gasInfo.Throughput, CharacterGasSource.CurrentOutputByType(gasInfo.Id)) * 100f / MyEngineConstants.UPDATE_STEPS_PER_SECOND;
                    TransferSuitGas(gasInfo.Id, gasInputPer100Frames, gasOutputPer100Frames);
                    m_gasOutputTime = MySandboxGame.TotalGamePlayTimeInMilliseconds;
                }
            }

            if (MySession.Static.Settings.EnableOxygen)
            {
                var cockpit = Character.Parent as MyCockpit;
                if (cockpit != null && cockpit.BlockDefinition.IsPressurized)
                {
                    if (Sync.IsServer && MySession.Static.SurvivalMode && !oxygenReplenished)
                    {
                        if (!Definition.NeedsOxygen)
                        {
                            if (cockpit.OxygenAmount >= Definition.OxygenConsumption)
                            {
                                cockpit.OxygenAmount -= Definition.OxygenConsumption;

                                noOxygenDamage  = false;
                                lowOxygenDamage = false;
                            }
                            else if (m_suitOxygenAmount >= Definition.OxygenConsumption)
                            {
                                m_suitOxygenAmount -= Definition.OxygenConsumption;
                                noOxygenDamage      = false;
                                lowOxygenDamage     = false;
                            }
                        }
                        else if (Definition.NeedsOxygen)
                        {
                            if (cockpit.OxygenFillLevel > 0f)
                            {
                                if (cockpit.OxygenAmount >= Definition.OxygenConsumption)
                                {
                                    cockpit.OxygenAmount -= Definition.OxygenConsumption;

                                    noOxygenDamage  = false;
                                    lowOxygenDamage = false;
                                }
                            }
                        }
                    }
                    EnvironmentOxygenLevel = cockpit.OxygenFillLevel;
                    isInEnvironment        = false;
                }
                else
                {
                    Vector3D pos = Character.GetHeadMatrix(true, true, false, true).Translation;
                    foreach (var entity in entities)
                    {
                        var grid = entity as MyCubeGrid;
                        // Oxygen can be present on small grids as well because of mods
                        if (grid != null)
                        {
                            var oxygenBlock = grid.GridSystems.GasSystem.GetSafeOxygenBlock(pos);
                            if (oxygenBlock.Room != null)
                            {
                                if (oxygenBlock.Room.OxygenLevel(grid.GridSize) > Definition.PressureLevelForLowDamage)
                                {
                                    if (Definition.NeedsOxygen)
                                    {
                                        lowOxygenDamage = false;
                                    }
                                }

                                if (oxygenBlock.Room.IsPressurized)
                                {
                                    EnvironmentOxygenLevel = oxygenBlock.Room.OxygenLevel(grid.GridSize);
                                    if (oxygenBlock.Room.OxygenAmount > Definition.OxygenConsumption)
                                    {
                                        if (Definition.NeedsOxygen)
                                        {
                                            noOxygenDamage = false;
                                            oxygenBlock.PreviousOxygenAmount = oxygenBlock.OxygenAmount() - Definition.OxygenConsumption;
                                            oxygenBlock.OxygenChangeTime     = MySandboxGame.TotalGamePlayTimeInMilliseconds;

                                            if (!oxygenReplenished)
                                            {
                                                oxygenBlock.Room.OxygenAmount -= Definition.OxygenConsumption;
                                            }
                                        }
                                        break;
                                    }
                                }
                                else
                                {
                                    EnvironmentOxygenLevel = oxygenBlock.Room.EnvironmentOxygen;
                                    if (EnvironmentOxygenLevel > Definition.OxygenConsumption)
                                    {
                                        if (Definition.NeedsOxygen)
                                        {
                                            noOxygenDamage = false;
                                        }
                                        break;
                                    }
                                }

                                isInEnvironment = false;
                            }
                        }
                    }
                }


                if (MySession.LocalCharacter == Character)
                {
                    if (m_oldSuitOxygenLevel >= 0.25f && SuitOxygenLevel < 0.25f)
                    {
                        MyHud.Notifications.Add(m_lowOxygenNotification);
                    }
                    else if (m_oldSuitOxygenLevel >= 0.05f && SuitOxygenLevel < 0.05f)
                    {
                        MyHud.Notifications.Add(m_criticalOxygenNotification);
                    }
                }
                m_oldSuitOxygenLevel = SuitOxygenLevel;
            }
            CharacterGasSink.Update();

            // Cannot early exit before calculations because of UI
            if (!Sync.IsServer || MySession.Static.CreativeMode || !MySession.Static.Settings.EnableOxygen)
            {
                return;
            }

            //Try to refill the suit from bottles in inventory
            if (SuitOxygenLevel < 0.3f && !Definition.NeedsOxygen)
            {
                var  items       = Character.Inventory.GetItems();
                bool bottlesUsed = false;
                foreach (var item in items)
                {
                    var oxygenContainer = item.Content as MyObjectBuilder_GasContainerObject;
                    if (oxygenContainer != null)
                    {
                        if (oxygenContainer.GasLevel == 0f)
                        {
                            continue;
                        }

                        var physicalItem = MyDefinitionManager.Static.GetPhysicalItemDefinition(oxygenContainer) as MyOxygenContainerDefinition;
                        if (physicalItem.StoredGasId != OxygenId)
                        {
                            continue;
                        }
                        float oxygenAmount = oxygenContainer.GasLevel * physicalItem.Capacity;

                        float transferredAmount = Math.Min(oxygenAmount, SuitOxygenAmountMissing);
                        oxygenContainer.GasLevel = (oxygenAmount - transferredAmount) / physicalItem.Capacity;

                        if (oxygenContainer.GasLevel < 0f)
                        {
                            oxygenContainer.GasLevel = 0f;
                        }

                        if (oxygenContainer.GasLevel > 1f)
                        {
                            Debug.Fail("Incorrect value");
                        }

                        Character.Inventory.UpdateGasAmount();

                        bottlesUsed = true;

                        SuitOxygenAmount += transferredAmount;
                        if (SuitOxygenLevel == 1f)
                        {
                            break;
                        }
                    }
                }
                if (bottlesUsed)
                {
                    if (MySession.LocalCharacter == Character)
                    {
                        ShowRefillFromBottleNotification();
                    }
                    else
                    {
                        Character.SyncObject.SendRefillFromBottle();
                    }
                }
            }

            foreach (var gasInfo in m_storedGases)
            {
                if (gasInfo.FillLevel < 0.3f) // Get rid of the specific oxygen version of this
                {
                    var  items       = Character.Inventory.GetItems();
                    bool bottlesUsed = false;
                    foreach (var item in items)
                    {
                        var gasContainer = item.Content as MyObjectBuilder_GasContainerObject;
                        if (gasContainer != null)
                        {
                            if (gasContainer.GasLevel == 0f)
                            {
                                continue;
                            }

                            var physicalItem = MyDefinitionManager.Static.GetPhysicalItemDefinition(gasContainer) as MyOxygenContainerDefinition;
                            if (physicalItem.StoredGasId != gasInfo.Id)
                            {
                                continue;
                            }
                            float gasAmount = gasContainer.GasLevel * physicalItem.Capacity;

                            float transferredAmount = Math.Min(gasAmount, (1f - gasInfo.FillLevel) * gasInfo.MaxCapacity);
                            gasContainer.GasLevel = Math.Max((gasAmount - transferredAmount) / physicalItem.Capacity, 0f);

                            if (gasContainer.GasLevel > 1f)
                            {
                                Debug.Fail("Incorrect value");
                            }

                            Character.Inventory.UpdateGasAmount();

                            bottlesUsed = true;

                            gasInfo.FillLevel = Math.Min(gasInfo.FillLevel + transferredAmount / gasInfo.MaxCapacity, 1f);
                            if (gasInfo.FillLevel == 1f)
                            {
                                break;
                            }
                        }
                    }
                    if (bottlesUsed)
                    {
                        if (MySession.LocalCharacter == Character)
                        {
                            ShowRefillFromBottleNotification();
                        }
                        else
                        {
                            Character.SyncObject.SendRefillFromBottle();
                        }
                    }
                }
            }

            // No oxygen found in room, try to get it from suit
            if (noOxygenDamage || lowOxygenDamage)
            {
                if (!Definition.NeedsOxygen && m_suitOxygenAmount > Definition.OxygenConsumption)
                {
                    if (!oxygenReplenished)
                    {
                        m_suitOxygenAmount -= Definition.OxygenConsumption;
                    }
                    if (m_suitOxygenAmount < 0f)
                    {
                        m_suitOxygenAmount = 0f;
                    }
                    noOxygenDamage  = false;
                    lowOxygenDamage = false;
                }

                if (isInEnvironment)
                {
                    if (EnvironmentOxygenLevel > Definition.PressureLevelForLowDamage)
                    {
                        lowOxygenDamage = false;
                    }
                    if (EnvironmentOxygenLevel > 0f)
                    {
                        noOxygenDamage = false;
                    }
                }
            }

            if (noOxygenDamage)
            {
                Character.DoDamage(Definition.DamageAmountAtZeroPressure, MyDamageType.LowPressure, true);
            }
            else if (lowOxygenDamage)
            {
                Character.DoDamage(1f, MyDamageType.Asphyxia, true);
            }

            Character.SyncObject.UpdateOxygen(SuitOxygenAmount);
        }
        private void UpdateOxygen()
        {
            // Try to find grids that might contain oxygen
            var entities = new List <MyEntity>();
            var aabb     = Character.PositionComp.WorldAABB;

            bool lowOxygenDamage   = MySession.Static.Settings.EnableOxygen;
            bool noOxygenDamage    = MySession.Static.Settings.EnableOxygen;
            bool isInEnvironment   = true;
            bool oxygenReplenished = false;

            EnvironmentOxygenLevel         = MyOxygenProviderSystem.GetOxygenInPoint(Character.PositionComp.GetPosition());
            OxygenLevelAtCharacterLocation = EnvironmentOxygenLevel;

            if (Sync.IsServer)
            {
                // Check for possibility that we are replenishing oxygen
                if (MySession.Static.Settings.EnableOxygen)
                {
                    GasData oxygenData;
                    if (TryGetGasData(OxygenId, out oxygenData))
                    {
                        float timeSinceLastUpdateSeconds = (MySession.Static.GameplayFrameCounter - oxygenData.LastOutputTime) * VRage.Game.MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS;

                        oxygenReplenished = CharacterGasSink.CurrentInputByType(OxygenId) * timeSinceLastUpdateSeconds > Definition.OxygenConsumption;

                        if (oxygenReplenished)
                        {
                            noOxygenDamage  = false;
                            lowOxygenDamage = false;
                        }
                    }
                }

                // Update Gases fill levels and capacity amounts
                foreach (GasData gasInfo in m_storedGases)
                {
                    var timeSinceLastOutputSeconds = (MySession.Static.GameplayFrameCounter - gasInfo.LastOutputTime) * VRage.Game.MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS;
                    var timeSinceLastInputSeconds  = (MySession.Static.GameplayFrameCounter - gasInfo.LastInputTime) * VRage.Game.MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS;

                    gasInfo.LastOutputTime = MySession.Static.GameplayFrameCounter;
                    gasInfo.LastInputTime  = MySession.Static.GameplayFrameCounter;

                    float gasOutputAmount = CharacterGasSource.CurrentOutputByType(gasInfo.Id) * timeSinceLastOutputSeconds;
                    float gasInputAmount  = CharacterGasSink.CurrentInputByType(gasInfo.Id) * timeSinceLastInputSeconds;

                    // Values that are not in distribution system yet and happend to inc/dec between updates
                    float outTransfer = -MathHelper.Clamp(gasInfo.NextGasTransfer, float.NegativeInfinity, 0f);
                    float inTransfer  = MathHelper.Clamp(gasInfo.NextGasTransfer, 0f, float.PositiveInfinity);
                    gasInfo.NextGasTransfer = 0f;

                    TransferSuitGas(ref gasInfo.Id, gasInputAmount + inTransfer, gasOutputAmount + outTransfer);
                }
            }

            if (MySession.Static.Settings.EnableOxygen)
            {
                var  cockpit           = Character.Parent as MyCockpit;
                bool OxygenFromCockpit = false;
                if (cockpit != null && cockpit.BlockDefinition.IsPressurized)
                {
                    if (Sync.IsServer && MySession.Static.SurvivalMode && !oxygenReplenished)
                    {
                        // Character is in pressurized room
                        if (!HelmetEnabled)
                        {
                            if (cockpit.OxygenFillLevel > 0f)
                            {
                                if (cockpit.OxygenAmount >= Definition.OxygenConsumption * Definition.OxygenConsumptionMultiplier)
                                {
                                    cockpit.OxygenAmount -= Definition.OxygenConsumption * Definition.OxygenConsumptionMultiplier;

                                    noOxygenDamage  = false;
                                    lowOxygenDamage = false;
                                }
                            }
                        }
                    }
                    EnvironmentOxygenLevel = cockpit.OxygenFillLevel;
                    isInEnvironment        = false;
                    OxygenFromCockpit      = true;
                }

                if (OxygenFromCockpit == false || (MyFakes.ENABLE_NEW_SOUNDS && MySession.Static.Settings.RealisticSound))
                {
                    OxygenSourceGrid = null;
                    Vector3D pos = Character.GetHeadMatrix(true, true, false, true).Translation;

                    MyGamePruningStructure.GetTopMostEntitiesInBox(ref aabb, entities);
                    foreach (var entity in entities)
                    {
                        var grid = entity as MyCubeGrid;
                        // Oxygen can be present on small grids as well because of mods
                        if (grid != null && grid.GridSystems.GasSystem != null)
                        {
                            var oxygenBlock = grid.GridSystems.GasSystem.GetSafeOxygenBlock(pos);
                            if (oxygenBlock.Room != null)
                            {
                                if (oxygenBlock.Room.OxygenLevel(grid.GridSize) > Definition.PressureLevelForLowDamage)
                                {
                                    if (!HelmetEnabled)
                                    {
                                        lowOxygenDamage = false;
                                    }
                                }

                                if (oxygenBlock.Room.IsPressurized)
                                {
                                    float oxygen = oxygenBlock.Room.OxygenLevel(grid.GridSize);
                                    if (!OxygenFromCockpit)
                                    {
                                        EnvironmentOxygenLevel = oxygen;
                                    }
                                    OxygenLevelAtCharacterLocation = oxygen;
                                    OxygenSourceGrid = grid;
                                    if (oxygenBlock.Room.OxygenAmount > Definition.OxygenConsumption * Definition.OxygenConsumptionMultiplier)
                                    {
                                        if (!HelmetEnabled)
                                        {
                                            noOxygenDamage = false;
                                            oxygenBlock.PreviousOxygenAmount = oxygenBlock.OxygenAmount() - Definition.OxygenConsumption * Definition.OxygenConsumptionMultiplier;
                                            oxygenBlock.OxygenChangeTime     = MySandboxGame.TotalGamePlayTimeInMilliseconds;

                                            if (!oxygenReplenished)
                                            {
                                                oxygenBlock.Room.OxygenAmount -= Definition.OxygenConsumption * Definition.OxygenConsumptionMultiplier;
                                            }
                                        }
                                        break;
                                    }
                                }
                                else
                                {
                                    float oxygen = oxygenBlock.Room.EnvironmentOxygen;
                                    OxygenLevelAtCharacterLocation = oxygen;

                                    if (!OxygenFromCockpit)
                                    {
                                        EnvironmentOxygenLevel = oxygen;

                                        if (!HelmetEnabled && EnvironmentOxygenLevel > Definition.OxygenConsumption * Definition.OxygenConsumptionMultiplier)
                                        {
                                            noOxygenDamage = false;
                                            break;
                                        }
                                    }
                                }

                                isInEnvironment = false;
                            }
                        }
                    }
                }


                if (MySession.Static.LocalCharacter == Character)
                {
                    if (m_oldSuitOxygenLevel >= 0.25f && SuitOxygenLevel < 0.25f)
                    {
                        MyHud.Notifications.Add(m_lowOxygenNotification);
                    }
                    else if (m_oldSuitOxygenLevel >= 0.05f && SuitOxygenLevel < 0.05f)
                    {
                        MyHud.Notifications.Add(m_criticalOxygenNotification);
                    }
                }
                m_oldSuitOxygenLevel = SuitOxygenLevel;
            }
            CharacterGasSink.Update();

            // Cannot early exit before calculations because of UI
            if (!Sync.IsServer || MySession.Static.CreativeMode || !MySession.Static.Settings.EnableOxygen)
            {
                return;
            }

            foreach (var gasInfo in m_storedGases)
            {
                if (gasInfo.FillLevel < GAS_REFILL_RATION) // Get rid of the specific oxygen version of this
                {
                    if (gasInfo.NextGasRefill == -1)
                    {
                        gasInfo.NextGasRefill = MySandboxGame.TotalGamePlayTimeInMilliseconds + m_gasRefillInterval * 1000;
                    }
                    if (MySandboxGame.TotalGamePlayTimeInMilliseconds < gasInfo.NextGasRefill)
                    {
                        continue;
                    }

                    gasInfo.NextGasRefill = -1;

                    var  items       = Character.GetInventory().GetItems();
                    bool bottlesUsed = false;
                    foreach (var item in items)
                    {
                        var gasContainer = item.Content as MyObjectBuilder_GasContainerObject;
                        if (gasContainer != null)
                        {
                            if (gasContainer.GasLevel == 0f)
                            {
                                continue;
                            }

                            var physicalItem = MyDefinitionManager.Static.GetPhysicalItemDefinition(gasContainer) as MyOxygenContainerDefinition;
                            if (physicalItem.StoredGasId != gasInfo.Id)
                            {
                                continue;
                            }
                            float gasAmount = gasContainer.GasLevel * physicalItem.Capacity;

                            float transferredAmount = Math.Min(gasAmount, (1f - gasInfo.FillLevel) * gasInfo.MaxCapacity);
                            gasContainer.GasLevel = Math.Max((gasAmount - transferredAmount) / physicalItem.Capacity, 0f);

                            if (gasContainer.GasLevel > 1f)
                            {
                                Debug.Fail("Incorrect value");
                            }

                            Character.GetInventory().UpdateGasAmount();

                            bottlesUsed = true;

                            TransferSuitGas(ref gasInfo.Id, transferredAmount, 0);
                            if (gasInfo.FillLevel == 1f)
                            {
                                break;
                            }
                        }
                    }
                    if (bottlesUsed)
                    {
                        if (MySession.Static.LocalCharacter == Character)
                        {
                            ShowRefillFromBottleNotification(gasInfo.Id);
                        }
                        else
                        {
                            Character.SendRefillFromBottle(gasInfo.Id);
                        }
                    }

                    var jetpack = Character.JetpackComp;
                    if (jetpack != null && jetpack.TurnedOn && jetpack.FuelDefinition != null && jetpack.FuelDefinition.Id == gasInfo.Id &&
                        gasInfo.FillLevel <= 0 &&
                        (Character.ControllerInfo.Controller != null && MySession.Static.IsAdminModeEnabled(Character.ControllerInfo.Controller.Player.Id.SteamId) == false || (MySession.Static.LocalCharacter != Character && Sync.IsServer == false)))
                    {
                        jetpack.SwitchThrusts();
                    }
                }
                else
                {
                    gasInfo.NextGasRefill = -1;
                }
            }

            // No oxygen or low oxygen found in room, try to get it from suit
            if (MySession.Static.Settings.EnableOxygen)
            {
                if (noOxygenDamage || lowOxygenDamage)
                {
                    if (HelmetEnabled && SuitOxygenAmount > Definition.OxygenConsumption * Definition.OxygenConsumptionMultiplier)
                    {
                        noOxygenDamage  = false;
                        lowOxygenDamage = false;
                    }

                    if (isInEnvironment && !HelmetEnabled)
                    {
                        if (EnvironmentOxygenLevel > Definition.PressureLevelForLowDamage)
                        {
                            lowOxygenDamage = false;
                        }
                        if (EnvironmentOxygenLevel > 0f)
                        {
                            noOxygenDamage = false;
                        }
                    }
                }

                m_oldSuitOxygenLevel = SuitOxygenLevel;

                if (noOxygenDamage)
                {
                    Character.DoDamage(Definition.DamageAmountAtZeroPressure, MyDamageType.LowPressure, true);
                }
                else if (lowOxygenDamage)
                {
                    Character.DoDamage(1f, MyDamageType.Asphyxia, true);
                }
            }

            Character.UpdateOxygen(SuitOxygenAmount);

            foreach (var gasInfo in m_storedGases)
            {
                Character.UpdateStoredGas(gasInfo.Id, gasInfo.FillLevel);
            }
        }