private void PressurizePostProcess()
        {
            m_prevCubeRoom = m_tempPrevCubeRoom;
            m_prevRooms = m_tempPrevRooms;

            for (int i = 0; i < m_cubeRoom.GetLength(0); i++)
                for (int j = 0; j < m_cubeRoom.GetLength(1); j++)
                    for (int k = 0; k < m_cubeRoom.GetLength(2); k++)
                    {
                        var oldRoom = m_cubeRoom[i, j, k];
                        var newRoom = m_tempRooms[m_cubeRoom[i, j, k].Room.Index];

                        m_cubeRoom[i, j, k].Room = newRoom;

                        if (!oldRoom.Room.IsPressurized)
                        {
                            newRoom.IsPressurized = false;
                            newRoom.EnvironmentOxygen = Math.Max(newRoom.EnvironmentOxygen, oldRoom.Room.EnvironmentOxygen);
                            newRoom.DepressurizationTime = MySandboxGame.TotalGamePlayTimeInMilliseconds;
                        }

                        Vector3I current = new Vector3I(i, j, k) + GridMin();

                        newRoom.blockCount++;
                    }

            for (int i = 0; i < m_cubeRoom.GetLength(0); i++)
                for (int j = 0; j < m_cubeRoom.GetLength(1); j++)
                    for (int k = 0; k < m_cubeRoom.GetLength(2); k++)
                    {
                        var room = m_cubeRoom[i, j, k].Room;
                        if (room != null && room.blockCount < 2)
                        {
                            m_cubeRoom[i, j, k].Room = null;
                        }
                    }


            m_rooms = new List<MyOxygenRoom>();
            int index = 0;
            foreach (var room in m_tempRooms)
            {
                if (room.blockCount > 1)
                {
                    room.Index = index;

                    m_rooms.Add(room);
                    index++;
                }
            }

            if (m_savedRooms != null && m_savedRooms.Count() != m_rooms.Count)
            {
                m_savedRooms = null;
            }

            if (m_savedRooms != null)
            {
                for (int i = 0; i < m_rooms.Count; i++)
                {
                    m_rooms[i].OxygenAmount = m_savedRooms[i];
                }
            }
            else
            {
                if (m_prevCubeRoom != null)
                {
                    for (int i = 0; i < m_prevCubeRoom.GetLength(0); i++)
                        for (int j = 0; j < m_prevCubeRoom.GetLength(1); j++)
                            for (int k = 0; k < m_prevCubeRoom.GetLength(2); k++)
                            {
                                var prevRoom = m_prevCubeRoom[i, j, k];
                                if (prevRoom.Room == null || prevRoom.Room.blockCount < 2)
                                    continue;

                                double cubeOxygen = prevRoom.Room.IsPressurized ? prevRoom.OxygenAmount() : prevRoom.Room.EnvironmentOxygen * GridCubeVolume();// prevRoom.Room.OxygenAmount / prevRoom.Room.blockCount;

                                Vector3I pos = new Vector3I(i, j, k) + m_prevMin - GridMin();

                                if (pos.X < 0 || pos.X >= m_cubeRoom.GetLength(0))
                                    continue;
                                if (pos.Y < 0 || pos.Y >= m_cubeRoom.GetLength(1))
                                    continue;
                                if (pos.Z < 0 || pos.Z >= m_cubeRoom.GetLength(2))
                                    continue;
                                
                                var currentRoom = m_cubeRoom[pos.X, pos.Y, pos.Z].Room;
                                m_cubeRoom[pos.X, pos.Y, pos.Z].PreviousOxygenAmount = (float)cubeOxygen;
                                m_cubeRoom[pos.X, pos.Y, pos.Z].OxygenChangeTime = MySandboxGame.TotalGamePlayTimeInMilliseconds;

                                if (currentRoom != null && currentRoom.blockCount > 1)
                                {
                                    currentRoom.OxygenAmount += cubeOxygen;
                                }

                                if (currentRoom != null && currentRoom.blockCount < 2)
                                {
                                    m_cubeRoom[pos.X, pos.Y, pos.Z].Room = null;
                                }
                            }

                    //Do breach detection in a separate pass to ensure that oxygen levels are correct
                    for (int i = 0; i < m_prevCubeRoom.GetLength(0); i++)
                        for (int j = 0; j < m_prevCubeRoom.GetLength(1); j++)
                            for (int k = 0; k < m_prevCubeRoom.GetLength(2); k++)
                            {
                                Vector3I pos = new Vector3I(i, j, k) + m_prevMin - GridMin();
                                if (!IsInGridBounds(pos, m_cubeRoom))
                                    continue;

                                var prevRoom = m_prevCubeRoom[i, j, k].Room;
                                var currentRoom = m_cubeRoom[pos.X, pos.Y, pos.Z].Room;
                                bool breachDetected = false;

                                //Do a preliminary scan to check if there is any new breach
                                for (int l = 0; l < 6; l++)
                                {
                                    Vector3I currNeighbourPos = pos + m_neighbours[l];
                                    if (!IsInGridBounds(currNeighbourPos, m_cubeRoom))
                                        continue;

                                    Vector3I prevNeighbourPos = new Vector3I(i, j, k) + m_neighbours[l];
                                    if (!IsInGridBounds(prevNeighbourPos, m_prevCubeRoom))
                                        continue;

                                    var currNeighbourRoom = m_cubeRoom[currNeighbourPos.X, currNeighbourPos.Y, currNeighbourPos.Z].Room;
                                    var prevNeighbourRoom = m_prevCubeRoom[prevNeighbourPos.X, prevNeighbourPos.Y, prevNeighbourPos.Z].Room;

                                    if (currNeighbourRoom == currentRoom && prevNeighbourRoom != prevRoom)
                                    {
                                        breachDetected = true;
                                    }
                                }

                                float minOxygenLevel = float.MaxValue;
                                float maxOxygenLevel = float.MinValue;
                                Vector3I minPos = Vector3I.Zero;
                                if (breachDetected)
                                {
                                    //Scan to determine if there is actually a difference in pressure levels
                                    for (int l = 0; l < 6; l++)
                                    {
                                        Vector3I currNeighbourPos = pos + m_neighbours[l];
                                        if (!IsInGridBounds(currNeighbourPos, m_cubeRoom))
                                            continue;

                                        Vector3I prevNeighbourPos = new Vector3I(i, j, k) + m_neighbours[l];
                                        if (!IsInGridBounds(prevNeighbourPos, m_prevCubeRoom))
                                            continue;

                                        var prevNeighbourRoom = m_prevCubeRoom[prevNeighbourPos.X, prevNeighbourPos.Y, prevNeighbourPos.Z].Room;
                                        if (prevNeighbourRoom == null)
                                            continue;

                                        if (IsPressurized(pos + GridMin(), currNeighbourPos + GridMin()))
                                            continue;

                                        float level = prevNeighbourRoom.IsPressurized ? prevNeighbourRoom.OxygenLevel(m_cubeGrid.GridSize) : prevNeighbourRoom.EnvironmentOxygen;

                                        if (level > maxOxygenLevel)
                                        {
                                            maxOxygenLevel = level;
                                        }
                                        if (level < minOxygenLevel)
                                        {
                                            minOxygenLevel = level;
                                            minPos = currNeighbourPos;
                                        }
                                    }
                                }

                                if (maxOxygenLevel - minOxygenLevel > 0.2f)
                                {
                                    Vector3D from = m_cubeGrid.GridIntegerToWorld(pos + GridMin());
                                    Vector3D to = m_cubeGrid.GridIntegerToWorld(minPos + GridMin());

                                    //Force
                                    float MAX_DISTANCE = 5f;

                                    var boundingSphere = new BoundingSphereD(to, MAX_DISTANCE);
                                    var decompressionDirection = Vector3D.Normalize(to - from);
                                    MyGamePruningStructure.GetAllEntitiesInSphere<MyEntity>(ref boundingSphere, m_entitiesInDepressurizationRange);

                                    foreach (var entity in m_entitiesInDepressurizationRange)
                                    {
                                        if (!(entity is MyCubeBlock) && !(entity is MyEntitySubpart) && entity.Physics != null)
                                        {
                                            var entityPos = entity.PositionComp.WorldMatrix.Translation;

                                            var forceDirection = (to - from) / 2f;
                                            var distance = (to - entityPos).Length();
                                            if (distance < MAX_DISTANCE)
                                            {
                                                forceDirection /= distance;

                                                if (Vector3D.Dot(decompressionDirection, forceDirection) < 0f)
                                                {
                                                    forceDirection = -forceDirection;
                                                }

                                                //float forceStrength = 500f * prevRoom.Room.OxygenLevel(m_cubeGrid.GridSize) * (1f - (float)distance / MAX_DISTANCE);
                                                float forceStrength = 500f * (1f - (float)distance / MAX_DISTANCE);

                                                MyDepressurizationForceInfo forceInfo;
                                                if (!m_forcesToApply.TryGetValue(entity, out forceInfo))
                                                {
                                                    forceInfo = new MyDepressurizationForceInfo();

                                                    forceInfo.Direction = forceDirection;
                                                    forceInfo.Strength = forceStrength;
                                                    forceInfo.ForceCount = 1;
                                                }
                                                else
                                                {
                                                    forceInfo.Direction = (forceInfo.Direction * forceInfo.ForceCount + forceDirection) / (forceInfo.ForceCount + 1);
                                                    forceInfo.Strength = (forceInfo.Strength * forceInfo.ForceCount + forceStrength) / (forceInfo.ForceCount + 1);
                                                    forceInfo.ForceCount++;
                                                }

                                                m_forcesToApply[entity] = forceInfo;
                                            }
                                        }
                                    }

                                    m_entitiesInDepressurizationRange.Clear();

                                    //Effect
                                    MyParticleEffect m_effect;
                                    if (MyParticlesManager.TryCreateParticleEffect(49, out m_effect))
                                    {
                                        var orientation = Matrix.CreateFromDir(to - from);
                                        orientation.Translation = from;
                                        m_effect.UserScale = 3f;

                                        m_effect.WorldMatrix = orientation;
                                        m_effect.AutoDelete = true;

                                        m_depressurizationEffects.Add(m_effect);
                                    }
                                }
                            }
                }

                foreach (var force in m_forcesToApply)
                {
                    var entity = force.Key;
                    var forceInfo = force.Value;

                    var character = entity as Sandbox.Game.Entities.Character.MyCharacter;
                    if (character != null)
                    {
                        if (character.Parent != null)
                        {
                            continue;
                        }
                        forceInfo.Strength *= 5f;
                    }

                    if (forceInfo.Strength > 1f)
                    {
                        if (character != null && character.IsDead == false)
                        {
                            character.EnableJetpack(true);
                        }

                        forceInfo.Direction.Normalize();
                        entity.Physics.AddForce(MyPhysicsForceType.APPLY_WORLD_IMPULSE_AND_WORLD_ANGULAR_IMPULSE, forceInfo.Direction * forceInfo.Strength, entity.PositionComp.WorldMatrix.Translation, null);
                    }
                }

                m_forcesToApply.Clear();

                foreach (var room in m_rooms)
                {
                    if (room.OxygenLevel(m_cubeGrid.GridSize) > 1.0)
                    {
                        room.OxygenAmount = room.MaxOxygen(m_cubeGrid.GridSize);
                    }

                }
            }

            m_prevMin = GridMin();
            isPressurizing = false;
            m_queueIndex = 0;
        }
Ejemplo n.º 2
0
        private void AddDepressurizationEffects(Vector3D from, Vector3D to)
        {
            //Force
            float MAX_DISTANCE = 5f;

            var boundingSphere         = new BoundingSphereD(to, MAX_DISTANCE);
            var decompressionDirection = Vector3D.Normalize(to - from);

            MyGamePruningStructure.GetAllEntitiesInSphere(ref boundingSphere, m_entitiesInDepressurizationRange);

            foreach (var entity in m_entitiesInDepressurizationRange)
            {
                if (!(entity is MyCubeBlock) && !(entity is MyEntitySubpart) && entity.Physics != null)
                {
                    var entityPos = entity.PositionComp.WorldMatrix.Translation;

                    var forceDirection = (to - from) / 2f;
                    var distance       = (to - entityPos).Length();
                    if (distance < MAX_DISTANCE)
                    {
                        forceDirection /= distance;

                        if (Vector3D.Dot(decompressionDirection, forceDirection) < 0f)
                        {
                            forceDirection = -forceDirection;
                        }

                        //float forceStrength = 500f * prevRoom.Room.OxygenLevel(m_cubeGrid.GridSize) * (1f - (float)distance / MAX_DISTANCE);
                        float forceStrength = 500f * (1f - (float)distance / MAX_DISTANCE);

                        MyDepressurizationForceInfo forceInfo;
                        if (!m_forcesToApply.TryGetValue(entity, out forceInfo))
                        {
                            forceInfo = new MyDepressurizationForceInfo();

                            forceInfo.Direction  = forceDirection;
                            forceInfo.Strength   = forceStrength;
                            forceInfo.ForceCount = 1;
                        }
                        else
                        {
                            forceInfo.Direction = (forceInfo.Direction * forceInfo.ForceCount + forceDirection) / (forceInfo.ForceCount + 1);
                            forceInfo.Strength  = (forceInfo.Strength * forceInfo.ForceCount + forceStrength) / (forceInfo.ForceCount + 1);
                            forceInfo.ForceCount++;
                        }

                        m_forcesToApply[entity] = forceInfo;
                    }
                }
            }

            m_entitiesInDepressurizationRange.Clear();

            //Effect
            MyParticleEffect effect;

            if (MyParticlesManager.TryCreateParticleEffect(49, out effect))
            {
                var orientation = Matrix.CreateFromDir(to - from);
                orientation.Translation = from;
                effect.UserScale        = 3f;

                effect.WorldMatrix = orientation;
                effect.AutoDelete  = true;

                m_depressurizationEffects.Add(effect);
            }
        }
Ejemplo n.º 3
0
        private void AddDepressurizationEffects(Vector3D from, Vector3D to)
        {
            //Force
            float MAX_DISTANCE = 5f;

            var boundingSphere = new BoundingSphereD(to, MAX_DISTANCE);
            var decompressionDirection = Vector3D.Normalize(to - from);
            MyGamePruningStructure.GetAllEntitiesInSphere<MyEntity>(ref boundingSphere, m_entitiesInDepressurizationRange);

            foreach (var entity in m_entitiesInDepressurizationRange)
            {
                if (!(entity is MyCubeBlock) && !(entity is MyEntitySubpart) && entity.Physics != null)
                {
                    var entityPos = entity.PositionComp.WorldMatrix.Translation;

                    var forceDirection = (to - from) / 2f;
                    var distance = (to - entityPos).Length();
                    if (distance < MAX_DISTANCE)
                    {
                        forceDirection /= distance;

                        if (Vector3D.Dot(decompressionDirection, forceDirection) < 0f)
                        {
                            forceDirection = -forceDirection;
                        }

                        //float forceStrength = 500f * prevRoom.Room.OxygenLevel(m_cubeGrid.GridSize) * (1f - (float)distance / MAX_DISTANCE);
                        float forceStrength = 500f * (1f - (float)distance / MAX_DISTANCE);

                        MyDepressurizationForceInfo forceInfo;
                        if (!m_forcesToApply.TryGetValue(entity, out forceInfo))
                        {
                            forceInfo = new MyDepressurizationForceInfo();

                            forceInfo.Direction = forceDirection;
                            forceInfo.Strength = forceStrength;
                            forceInfo.ForceCount = 1;
                        }
                        else
                        {
                            forceInfo.Direction = (forceInfo.Direction * forceInfo.ForceCount + forceDirection) / (forceInfo.ForceCount + 1);
                            forceInfo.Strength = (forceInfo.Strength * forceInfo.ForceCount + forceStrength) / (forceInfo.ForceCount + 1);
                            forceInfo.ForceCount++;
                        }

                        m_forcesToApply[entity] = forceInfo;
                    }
                }
            }

            m_entitiesInDepressurizationRange.Clear();

            //Effect
            MyParticleEffect m_effect;
            if (MyParticlesManager.TryCreateParticleEffect(49, out m_effect))
            {
                var orientation = Matrix.CreateFromDir(to - from);
                orientation.Translation = from;
                m_effect.UserScale = 3f;

                m_effect.WorldMatrix = orientation;
                m_effect.AutoDelete = true;

                m_depressurizationEffects.Add(m_effect);
            }
        }