예제 #1
0
 private void GetCharactersInBoundingBox(BoundingBoxD boundingBox, List <MyCharacter> characters)
 {
     MyGamePruningStructure.GetAllTopMostEntitiesInBox <MyEntity>(ref boundingBox, m_entitiesInRange);
     foreach (var entity in m_entitiesInRange)
     {
         var character = entity as MyCharacter;
         if (character != null)
         {
             characters.Add(character);
         }
     }
     m_entitiesInRange.Clear();
 }
예제 #2
0
        public override void UpdateAfterSimulation10()
        {
            base.UpdateAfterSimulation10();

            if (!Sync.IsServer || !IsWorking || !PowerReceiver.IsPowered)
            {
                return;
            }

            var rotation1 = Quaternion.CreateFromForwardUp(WorldMatrix.Forward, WorldMatrix.Up);
            var position1 = PositionComp.GetPosition() + Vector3D.Transform(PositionComp.LocalVolume.Center + (m_fieldMax + m_fieldMin) * 0.5f, rotation1);

            VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("Recreate Field");
            if (m_recreateField)
            {
                m_recreateField = false;
                m_fieldShape.RemoveReference();
                m_fieldShape = GetHkShape();
                PowerReceiver.Update();
            }
            VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock();

            var boundingBox = new BoundingBoxD(m_fieldMin, m_fieldMax).Translate(PositionComp.LocalVolume.Center).Transform(WorldMatrix.GetOrientation()).Translate(PositionComp.GetPosition());

            m_potentialPenetrations.Clear();
            MyGamePruningStructure.GetAllTopMostEntitiesInBox <MyEntity>(ref boundingBox, m_potentialPenetrations);

            VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("Sensor Physics");
            LastDetectedEntity = null;
            if (IsActive)
            {
                bool empty = true;
                foreach (var entity in m_potentialPenetrations)
                {
                    if (ShouldDetect(entity))
                    {
                        if (entity.Physics == null || !entity.Physics.Enabled)
                        {
                            continue;
                        }

                        Quaternion rotation2;
                        Vector3    posDiff;
                        HkShape?   shape2;

                        if (entity.Physics.RigidBody != null)
                        {
                            shape2 = entity.Physics.RigidBody.GetShape();

                            var worldMatrix = entity.WorldMatrix;
                            rotation2 = Quaternion.CreateFromForwardUp(worldMatrix.Forward, worldMatrix.Up);
                            posDiff   = entity.PositionComp.GetPosition() - position1;
                            if (entity is MyVoxelMap)
                            {
                                var voxel = entity as MyVoxelMap;
                                posDiff -= voxel.Storage.Size / 2;
                            }
                        }
                        else if (entity.Physics.CharacterProxy != null)
                        {
                            shape2 = entity.Physics.CharacterProxy.GetShape();
                            var worldMatrix = entity.WorldMatrix;
                            rotation2 = Quaternion.CreateFromForwardUp(worldMatrix.Forward, worldMatrix.Up);
                            posDiff   = entity.PositionComp.GetPosition() - position1;
                        }
                        else
                        {
                            continue;
                        }

                        if (entity.Physics.HavokWorld.IsPenetratingShapeShape(m_fieldShape, ref Vector3.Zero, ref rotation1, shape2.Value, ref posDiff, ref rotation2))
                        {
                            LastDetectedEntity = entity;
                            empty = false;
                            break;
                        }
                    }
                }

                if (empty)
                {
                    IsActive = false;
                }
            }
            else
            {
                foreach (var entity in m_potentialPenetrations)
                {
                    if (ShouldDetect(entity))
                    {
                        if (entity.Physics == null || !entity.Physics.Enabled)
                        {
                            continue;
                        }

                        Quaternion rotation2;
                        Vector3    posDiff;
                        HkShape?   shape2;

                        if (entity.Physics.RigidBody != null)
                        {
                            shape2 = entity.Physics.RigidBody.GetShape();

                            var worldMatrix = entity.WorldMatrix;
                            rotation2 = Quaternion.CreateFromForwardUp(worldMatrix.Forward, worldMatrix.Up);
                            posDiff   = entity.PositionComp.GetPosition() - position1;
                            if (entity is MyVoxelMap)
                            {
                                var voxel = entity as MyVoxelMap;
                                posDiff -= voxel.Storage.Size / 2;
                            }
                        }
                        else if (entity.Physics.CharacterProxy != null)
                        {
                            shape2 = entity.Physics.CharacterProxy.GetShape();
                            var worldMatrix = entity.WorldMatrix;
                            rotation2 = Quaternion.CreateFromForwardUp(worldMatrix.Forward, worldMatrix.Up);
                            posDiff   = entity.PositionComp.GetPosition() - position1;
                        }
                        else
                        {
                            continue;
                        }

                        if (entity.Physics.HavokWorld.IsPenetratingShapeShape(m_fieldShape, ref Vector3.Zero, ref rotation1, shape2.Value, ref posDiff, ref rotation2))
                        {
                            LastDetectedEntity = entity;
                            IsActive           = true;
                            break;
                        }
                    }
                }
            }
            m_potentialPenetrations.Clear();
            VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock();
        }
예제 #3
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);
        }
예제 #4
0
        public override void UpdateAfterSimulation10()
        {
            base.UpdateAfterSimulation10();

            if (!Sync.IsServer || !IsWorking || !ResourceSink.IsPowered)
            {
                return;
            }

            var rotation1 = Quaternion.CreateFromForwardUp(WorldMatrix.Forward, WorldMatrix.Up);
            var position1 = PositionComp.GetPosition() + Vector3D.Transform(PositionComp.LocalVolume.Center + (m_fieldMax + m_fieldMin) * 0.5f, rotation1);

            VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("Recreate Field");
            if (m_recreateField)
            {
                m_recreateField = false;
                m_fieldShape.RemoveReference();
                m_fieldShape = GetHkShape();
                ResourceSink.Update();
            }
            VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock();

            var boundingBox = new BoundingBoxD(m_fieldMin, m_fieldMax).Translate(PositionComp.LocalVolume.Center).Transform(WorldMatrix.GetOrientation()).Translate(PositionComp.GetPosition());

            m_potentialPenetrations.Clear();
            MyGamePruningStructure.GetAllTopMostEntitiesInBox(ref boundingBox, m_potentialPenetrations);

            m_potentialVoxelPenetrations.Clear();
            MyGamePruningStructure.GetAllVoxelMapsInBox(ref boundingBox, m_potentialVoxelPenetrations);

            VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("Sensor Physics");
            LastDetectedEntity = null;
            if (IsActive)
            {
                bool empty = true;
                foreach (var entity in m_potentialPenetrations)
                {
                    if (entity is MyVoxelBase)
                    {
                        continue;
                    }
                    if (ShouldDetect(entity))
                    {
                        Quaternion rotation2;
                        Vector3    posDiff;
                        HkShape?   shape2;
                        if (GetPropertiesFromEntity(entity, ref position1, out rotation2, out posDiff, out shape2))
                        {
                            if (entity.Physics.HavokWorld.IsPenetratingShapeShape(m_fieldShape, ref Vector3.Zero, ref rotation1, shape2.Value, ref posDiff, ref rotation2))
                            {
                                LastDetectedEntity = entity;
                                empty = false;
                                break;
                            }
                        }
                    }
                }

                foreach (var entity in m_potentialVoxelPenetrations)
                {
                    if (ShouldDetect(entity))
                    {
                        Quaternion rotation2;
                        Vector3    posDiff;
                        HkShape?   shape2;
                        if (GetPropertiesFromEntity(entity, ref position1, out rotation2, out posDiff, out shape2))
                        {
                            if (entity.Physics.HavokWorld.IsPenetratingShapeShape(m_fieldShape, ref Vector3.Zero, ref rotation1, shape2.Value, ref posDiff, ref rotation2))
                            {
                                LastDetectedEntity = entity;
                                empty = false;
                                break;
                            }
                        }
                    }
                }

                if (empty)
                {
                    IsActive = false;
                }
            }
            else
            {
                foreach (var entity in m_potentialPenetrations)
                {
                    if (entity is MyVoxelBase)
                    {
                        continue;
                    }
                    if (ShouldDetect(entity))
                    {
                        Quaternion rotation2;
                        Vector3    posDiff;
                        HkShape?   shape2;
                        if (GetPropertiesFromEntity(entity, ref position1, out rotation2, out posDiff, out shape2))
                        {
                            if (entity.Physics.HavokWorld.IsPenetratingShapeShape(m_fieldShape, ref Vector3.Zero, ref rotation1, shape2.Value, ref posDiff, ref rotation2))
                            {
                                LastDetectedEntity = entity;
                                IsActive           = true;
                                break;
                            }
                        }
                    }
                }

                foreach (var entity in m_potentialVoxelPenetrations)
                {
                    if (ShouldDetect(entity))
                    {
                        Quaternion rotation2;
                        Vector3    posDiff;
                        HkShape?   shape2;
                        if (GetPropertiesFromEntity(entity, ref position1, out rotation2, out posDiff, out shape2))
                        {
                            if (entity.Physics.HavokWorld.IsPenetratingShapeShape(m_fieldShape, ref Vector3.Zero, ref rotation1, shape2.Value, ref posDiff, ref rotation2))
                            {
                                LastDetectedEntity = entity;
                                IsActive           = true;
                                break;
                            }
                        }
                    }
                }
            }
            m_potentialPenetrations.Clear();
            m_potentialVoxelPenetrations.Clear();
            VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock();
        }
예제 #5
0
        private Vector3D?FindSuitableJumpLocation(Vector3D desiredLocation)
        {
            BoundingBoxD shipBBox   = GetAggregateBBox();
            BoundingBoxD regionBBox = shipBBox.GetInflated(shipBBox.HalfExtents * 100);

            regionBBox.Translate(desiredLocation - regionBBox.Center);
            shipBBox.Inflate(shipBBox.HalfExtents);


            MyProceduralWorldGenerator.Static.OverlapAllPlanetSeedsInSphere(new BoundingSphereD(regionBBox.Center, regionBBox.HalfExtents.AbsMax()), m_objectsInRange);
            Vector3D currentSearchPosition = desiredLocation;

            foreach (var planet in m_objectsInRange)
            {
                if (planet.BoundingVolume.Contains(currentSearchPosition) != ContainmentType.Disjoint)
                {
                    Vector3D v = currentSearchPosition - planet.BoundingVolume.Center;
                    v.Normalize();
                    v *= planet.BoundingVolume.HalfExtents * 1.5;
                    currentSearchPosition = planet.BoundingVolume.Center + v;
                    break;
                }
            }
            m_objectsInRange.Clear();

            MyProceduralWorldGenerator.Static.OverlapAllAsteroidSeedsInSphere(new BoundingSphereD(regionBBox.Center, regionBBox.HalfExtents.AbsMax()), m_objectsInRange);
            foreach (var asteroid in m_objectsInRange)
            {
                m_obstaclesInRange.Add(asteroid.BoundingVolume);
            }
            m_objectsInRange.Clear();

            MyGamePruningStructure.GetAllTopMostEntitiesInBox <MyEntity>(ref regionBBox, m_entitiesInRange);

            // Inflate the obstacles so we only need to check the center of the ship for collisions
            foreach (var entity in m_entitiesInRange)
            {
                if (!(entity is MyPlanet))
                {
                    m_obstaclesInRange.Add(entity.PositionComp.WorldAABB.GetInflated(shipBBox.HalfExtents));
                }
            }

            int maxStepCount = 10;
            int stepCount    = 0;

            // When we collide with an obsticle, we add it here
            BoundingBoxD?aggregateCollidedObstacles = null;
            bool         obstructed = false;
            bool         found      = false;

            while (stepCount < maxStepCount)
            {
                stepCount++;
                obstructed = false;
                foreach (var obstacle in m_obstaclesInRange)
                {
                    var contains = obstacle.Contains(currentSearchPosition);
                    if (contains == ContainmentType.Contains ||
                        contains == ContainmentType.Intersects)
                    {
                        if (!aggregateCollidedObstacles.HasValue)
                        {
                            aggregateCollidedObstacles = obstacle;
                        }
                        aggregateCollidedObstacles = aggregateCollidedObstacles.Value.Include(obstacle);
                        aggregateCollidedObstacles = aggregateCollidedObstacles.Value.Inflate(1.0);
                        currentSearchPosition      = ClosestPointOnBounds(aggregateCollidedObstacles.Value, currentSearchPosition);
                        obstructed = true;
                        break;
                    }
                }

                if (!obstructed)
                {
                    // No obstacle found, return current search position
                    found = true;
                    break;
                }
            }

            m_obstaclesInRange.Clear();
            m_entitiesInRange.Clear();
            m_objectsInRange.Clear();

            if (found)
            {
                return(currentSearchPosition);
            }
            else
            {
                return(null);
            }
        }
예제 #6
0
        private void UpdateOxygen()
        {
            if (!MySession.Static.Settings.EnableOxygen)
            {
                return;
            }

            // Try to find grids that might contain oxygen
            var entities = new List <MyEntity>();
            var aabb     = PositionComp.WorldAABB;

            MyGamePruningStructure.GetAllTopMostEntitiesInBox <MyEntity>(ref aabb, entities);
            bool lowOxygenDamage = true;
            bool noOxygenDamage  = true;
            bool isInEnvironment = true;

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

            var cockpit = Parent as MyCockpit;

            if (cockpit != null && cockpit.BlockDefinition.IsPressurized)
            {
                if (Sync.IsServer && MySession.Static.SurvivalMode)
                {
                    if (!Definition.NeedsOxygen && m_suitOxygenAmount > Definition.OxygenConsumption)
                    {
                        m_suitOxygenAmount -= Definition.OxygenConsumption;
                        if (m_suitOxygenAmount < 0f)
                        {
                            m_suitOxygenAmount = 0f;
                        }
                    }

                    if (cockpit.OxygenLevel > 0f)
                    {
                        if (Definition.NeedsOxygen)
                        {
                            if (cockpit.OxygenAmount >= Definition.OxygenConsumption)
                            {
                                cockpit.OxygenAmount -= Definition.OxygenConsumption;

                                noOxygenDamage  = false;
                                lowOxygenDamage = false;
                            }
                        }
                        else
                        {
                            float oxygenTransferred = Math.Min(SuitOxygenAmountMissing, cockpit.OxygenAmount);
                            oxygenTransferred = Math.Min(oxygenTransferred, MyOxygenConstants.OXYGEN_REGEN_PER_SECOND);

                            cockpit.OxygenAmount -= oxygenTransferred;
                            SuitOxygenAmount     += oxygenTransferred;

                            noOxygenDamage  = false;
                            lowOxygenDamage = false;
                        }
                    }
                }
                EnvironmentOxygenLevel = cockpit.OxygenLevel;
                isInEnvironment        = false;
            }
            else
            {
                Vector3D pos = PositionComp.WorldMatrix.Translation;
                if (m_headBoneIndex != -1)
                {
                    pos = (BoneAbsoluteTransforms[m_headBoneIndex] * WorldMatrix).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.OxygenSystem.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;
                                        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 == this)
            {
                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;

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

            //TODO(AF) change this to a constant
            //Try to refill the suit from bottles in inventory
            if (SuitOxygenLevel < 0.3f && !Definition.NeedsOxygen)
            {
                var  items       = Inventory.GetItems();
                bool bottlesUsed = false;
                foreach (var item in items)
                {
                    var oxygenContainer = item.Content as MyObjectBuilder_OxygenContainerObject;
                    if (oxygenContainer != null)
                    {
                        if (oxygenContainer.OxygenLevel == 0f)
                        {
                            continue;
                        }

                        var   physicalItem = MyDefinitionManager.Static.GetPhysicalItemDefinition(oxygenContainer) as MyOxygenContainerDefinition;
                        float oxygenAmount = oxygenContainer.OxygenLevel * physicalItem.Capacity;

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

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


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

                        Inventory.UpdateOxygenAmount();
                        Inventory.SyncOxygenContainerLevel(item.ItemId, oxygenContainer.OxygenLevel);

                        bottlesUsed = true;

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

            // No oxygen found in room, try to get it from suit
            if (noOxygenDamage || lowOxygenDamage)
            {
                if (!Definition.NeedsOxygen && m_suitOxygenAmount > Definition.OxygenConsumption)
                {
                    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)
            {
                DoDamage(Definition.DamageAmountAtZeroPressure, MyDamageType.LowPressure, true);
            }
            else if (lowOxygenDamage)
            {
                DoDamage(1f, MyDamageType.Asphyxia, true);
            }

            SyncObject.UpdateOxygen(SuitOxygenAmount);
        }