using Sandbox.ModAPI.Ingame; using SpaceEngineers.Game.ModAPI.Ingame; using System.Collections; using System.Collections.Generic; using VRageMath; namespace IngameScript { partial class Program { public class AirZone { public string Name { get; private set; } public bool Triggered { get; private set; } = false; public List Vents { get; } = new List(); private Program _program; private List _doors = new List(); private List _displays = new List(); private List _lights = new List(); private PrefixedConsole _console; private Sequencer _sequencer; private const float TriggerLevel = 0.75F; public AirZone(Program program, string zoneName) { Name = zoneName; _program = program; _console = new PrefixedConsole(_program.Console, Name); _sequencer = new Sequencer(_program, Name); } public void AddBlock(IMyTerminalBlock block) { if (block is IMyAirVent) { Vents.Add(block as IMyAirVent); } else if (block is IMyDoor) { _doors.Add(block as IMyDoor); SequenceableDoor wrapped = SequenceableFactory.MakeSequenceable( block as IMyDoor, _program.Ini, "airMonitor") as SequenceableDoor; wrapped.Step = 0; wrapped.DeployOpen = false; wrapped.LockOpen = false; wrapped.LockClosed = true; _sequencer.AddBlock(wrapped); } 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 } public void Reset() { _console.Print("Resetting sensor."); Triggered = false; } // This enumerator should run forever. public IEnumerator Monitor() { while (true) { foreach (IMyAirVent vent in Vents) { if (vent.GetOxygenLevel() < TriggerLevel) Triggered = true; } // TODO: add informational lights per-zone if (Triggered == true) { _console.Print($"Low pressure alarm triggered."); foreach (IMyLightingBlock light in _lights) { light.Enabled = true; light.Color = Color.Red; } // close the doors IEnumerator job = _sequencer.RunSequence(true); 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. _program.Runtime.UpdateFrequency |= UpdateFrequency.Once; yield return true; } job.Dispose(); while (Triggered) yield return true; // unlock the doors, but we'll leave them closed. foreach (IMyDoor door in _doors) { door.Enabled = true; } foreach (IMyLightingBlock light in _lights) { light.Enabled = true; light.Color = Color.White; } } yield return true; } } } } }