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