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