using Sandbox.ModAPI.Ingame; using SpaceEngineers.Game.ModAPI.Ingame; using System.Collections.Generic; using VRageMath; namespace IngameScript { partial class Program { public class AirZone { public string Name { get; private set; } public bool Triggered { get { foreach (IMyAirVent vent in Vents) { if (vent.GetOxygenLevel() < TriggerLevel || vent.Status == VentStatus.Depressurized) return true; } return false; } } public float OxygenLevel { get { float ret = 100F; foreach (IMyAirVent vent in Vents) { if (vent.GetOxygenLevel() < ret) ret = vent.GetOxygenLevel(); } return ret; } } public List Vents { get; } = new List(); private Program _program; // private List _displays = new List(); // TODO: add single-zone displays private List _lights = new List(); private List _doors = new List(); private PrefixedConsole _console; private ActionSequence _sealBulkheads; // actions to perform when the pressure alarm is triggered private const float TriggerLevel = 0.75F; public AirZone(Program program, string zoneName) { Name = zoneName; _program = program; _console = new PrefixedConsole(_program.Console, Name); _sealBulkheads = new ActionSequence(Name); } public void AddDoor(AirDoor door) { _doors.Add(door); IMyDoor doorBlock = door.Door; _sealBulkheads.Add(0, new BlockActionDoor( doorBlock, DoorAction.Close, true )); } public void AddBlock(IMyTerminalBlock block) { if (block is IMyAirVent) { Vents.Add(block as IMyAirVent); } else if (block is IMyLightingBlock) { _lights.Add(block as IMyLightingBlock); } else { _console.Print("Tried to add incompatible block '{block.CustomName}'"); } // TODO: support for arbitrary (sub-)sequences here could be powerful } // This enumerator should run forever. public IEnumerator Monitor() { while (true) { if (Triggered == true) { _console.Print($"Low pressure alarm triggered."); // close the doors IEnumerator job = _sealBulkheads.Run(); while (job.MoveNext()) { // It would be nice if the API had UpdateFrequency.Once10, e.g. "re-run in 10 ticks and then clear the flag" // We'll just monitor every tick instead. setTriggeredStates(); _program.Runtime.UpdateFrequency |= UpdateFrequency.Once; yield return true; } job.Dispose(); while (Triggered) { setTriggeredStates(); yield return true; } _console.Print("Air pressure returned to safe levels."); } yield return true; } } private void setTriggeredStates() { foreach (IMyLightingBlock light in _lights) light.Color = Color.Red; foreach (AirDoor door in _doors) door.Triggered = true; } } } }