Added the ability to use display screens in cockpits and LCD panels to display air monitoring data.
This commit is contained in:
parent
136938a3e3
commit
5db025bb47
|
@ -9,30 +9,38 @@ namespace IngameScript
|
||||||
{
|
{
|
||||||
public class AirZone
|
public class AirZone
|
||||||
{
|
{
|
||||||
public bool Triggered = false;
|
public bool Triggered { get; private set; } = false;
|
||||||
|
public string Name { get; private set; }
|
||||||
|
public List<IMyAirVent> Vents { get; private set; }
|
||||||
|
|
||||||
private MyIni _ini;
|
private MyIni _ini;
|
||||||
private List<IMyAirVent> _vents;
|
private List<IMyDoor> _doors;
|
||||||
|
private List<IMyTextSurface> _displays;
|
||||||
private PrefixedConsole _console;
|
private PrefixedConsole _console;
|
||||||
private Sequencer _sequencer;
|
private Sequencer _sequencer;
|
||||||
|
|
||||||
private const float TriggerLevel = 0.75F;
|
private const float TriggerLevel = 0.75F;
|
||||||
|
|
||||||
public AirZone(string zoneName, MyIni ini, IConsole console)
|
public AirZone(string zoneName, MyIni ini, IConsole console)
|
||||||
{
|
{
|
||||||
|
Name = zoneName;
|
||||||
_ini = ini;
|
_ini = ini;
|
||||||
_console = new PrefixedConsole(console, zoneName);
|
_console = new PrefixedConsole(console, zoneName);
|
||||||
_sequencer = new Sequencer(zoneName, _console);
|
_sequencer = new Sequencer(zoneName, _console);
|
||||||
_vents = new List<IMyAirVent>();
|
Vents = new List<IMyAirVent>();
|
||||||
|
_doors = new List<IMyDoor>();
|
||||||
|
_displays = new List<IMyTextSurface>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddBlock(IMyTerminalBlock block)
|
public void AddBlock(IMyTerminalBlock block)
|
||||||
{
|
{
|
||||||
if (block is IMyAirVent)
|
if (block is IMyAirVent)
|
||||||
{
|
{
|
||||||
_vents.Add(block as IMyAirVent);
|
Vents.Add(block as IMyAirVent);
|
||||||
}
|
}
|
||||||
else if (block is IMyDoor)
|
else if (block is IMyDoor)
|
||||||
{
|
{
|
||||||
|
_doors.Add(block as IMyDoor);
|
||||||
SequenceableDoor wrapped = SequenceableFactory.MakeSequenceable(block as IMyDoor, _ini, "airMonitor") as SequenceableDoor;
|
SequenceableDoor wrapped = SequenceableFactory.MakeSequenceable(block as IMyDoor, _ini, "airMonitor") as SequenceableDoor;
|
||||||
wrapped.Step = 0;
|
wrapped.Step = 0;
|
||||||
wrapped.DeployOpen = false;
|
wrapped.DeployOpen = false;
|
||||||
|
@ -47,28 +55,49 @@ namespace IngameScript
|
||||||
// TODO: support for arbitrary (sub-)sequences here could be powerful
|
// TODO: support for arbitrary (sub-)sequences here could be powerful
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
_console.Print("Resetting sensor.");
|
||||||
|
Triggered = false;
|
||||||
|
}
|
||||||
|
|
||||||
// This enumerator should run forever.
|
// This enumerator should run forever.
|
||||||
public IEnumerator<bool> Monitor()
|
public IEnumerator<bool> Monitor()
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
foreach (IMyAirVent vent in _vents)
|
foreach (IMyAirVent vent in Vents)
|
||||||
{
|
{
|
||||||
if (vent.GetOxygenLevel() < TriggerLevel) Triggered = true;
|
if (vent.GetOxygenLevel() < TriggerLevel) Triggered = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Triggered == true)
|
if (Triggered == true)
|
||||||
{
|
{
|
||||||
|
_console.Print($"Low pressure alarm triggered.");
|
||||||
// close the doors
|
// close the doors
|
||||||
IEnumerator<bool> job = _sequencer.RunSequence(true);
|
IEnumerator<bool> job = _sequencer.RunSequence(true);
|
||||||
while (job.MoveNext()) yield return true;
|
while (job.MoveNext()) yield return true;
|
||||||
|
|
||||||
// noop until manually reset
|
while (Triggered)
|
||||||
while (Triggered) yield return true;
|
{
|
||||||
|
// if any of the doors become re-enabled, reset and unlock all of them;
|
||||||
|
// think of it as a player manually overriding the safety protocols.
|
||||||
|
// Note that this means resets propagate across zones that share doors,
|
||||||
|
// which will likely be all of them. Which is a *little* bit of a
|
||||||
|
// bug, but it's better than never re-triggering
|
||||||
|
foreach (IMyDoor door in _doors)
|
||||||
|
{
|
||||||
|
if (door.Enabled)
|
||||||
|
{
|
||||||
|
Reset();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
yield return true;
|
||||||
|
}
|
||||||
|
|
||||||
// open the doors
|
// unlock the doors, but we'll leave them closed.
|
||||||
job = _sequencer.RunSequence(false);
|
foreach (IMyDoor door in _doors) { door.Enabled = true; }
|
||||||
while (job.MoveNext()) yield return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
yield return true;
|
yield return true;
|
||||||
|
|
|
@ -25,9 +25,13 @@ namespace IngameScript
|
||||||
private MyIni _ini;
|
private MyIni _ini;
|
||||||
private Console _console;
|
private Console _console;
|
||||||
private MyCommandLine _cli;
|
private MyCommandLine _cli;
|
||||||
|
private int _totalTicks = 0;
|
||||||
|
|
||||||
private Dictionary<string, AirZone> _zones;
|
private Dictionary<string, AirZone> _zones;
|
||||||
private List<IEnumerator<bool>> _jobs;
|
private List<IEnumerator<bool>> _jobs;
|
||||||
private int _totalTicks = 0;
|
private List<IMyTextSurface> _displays;
|
||||||
|
private StringBuilder _displayBuffer;
|
||||||
|
private List<IMyGasTank> _oxygenTanks;
|
||||||
|
|
||||||
public Program()
|
public Program()
|
||||||
{
|
{
|
||||||
|
@ -36,6 +40,9 @@ namespace IngameScript
|
||||||
_console = new Console(this, _ini);
|
_console = new Console(this, _ini);
|
||||||
_zones = new Dictionary<string, AirZone>();
|
_zones = new Dictionary<string, AirZone>();
|
||||||
_jobs = new List<IEnumerator<bool>>();
|
_jobs = new List<IEnumerator<bool>>();
|
||||||
|
_displays = new List<IMyTextSurface>();
|
||||||
|
_displayBuffer = new StringBuilder();
|
||||||
|
_oxygenTanks = new List<IMyGasTank>();
|
||||||
|
|
||||||
// Find all tagged objects and build out zones
|
// Find all tagged objects and build out zones
|
||||||
List<IMyTerminalBlock> blocks = new List<IMyTerminalBlock>();
|
List<IMyTerminalBlock> blocks = new List<IMyTerminalBlock>();
|
||||||
|
@ -44,6 +51,34 @@ namespace IngameScript
|
||||||
{
|
{
|
||||||
_ini.TryParse(block.CustomData);
|
_ini.TryParse(block.CustomData);
|
||||||
string[] zones = new string[] { };
|
string[] zones = new string[] { };
|
||||||
|
|
||||||
|
// TODO: how do we display text on e.g. decorative console blocks?
|
||||||
|
// They have configurable screens but the docs say they don't implement this.
|
||||||
|
// Meanwhile *every* functional block seems to implement IMyTextSurfaceProvider...
|
||||||
|
// It'd probably be safe to just check SurfaceCount... experiment with this later
|
||||||
|
if (block is IMyTextSurface)
|
||||||
|
{
|
||||||
|
_console.Print($"Adding monitoring display '{block.CustomName}'");
|
||||||
|
_displays.Add(block as IMyTextSurface);
|
||||||
|
}
|
||||||
|
if (_ini.Get("airMonitor", "display").ToString() != "")
|
||||||
|
{
|
||||||
|
int displayIndex = _ini.Get("airMonitor", "display").ToInt32();
|
||||||
|
IMyTextSurfaceProvider provider = block as IMyTextSurfaceProvider;
|
||||||
|
if (provider.SurfaceCount <= displayIndex)
|
||||||
|
{
|
||||||
|
_console.Print($"Invalid display index '{displayIndex}' in block '{block.CustomName}'");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_displays.Add(provider.GetSurface(displayIndex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (block is IMyGasTank)
|
||||||
|
{
|
||||||
|
_oxygenTanks.Add(block as IMyGasTank);
|
||||||
|
}
|
||||||
|
|
||||||
if (_ini.Get("airMonitor", "zones").ToString() != "")
|
if (_ini.Get("airMonitor", "zones").ToString() != "")
|
||||||
{
|
{
|
||||||
zones = _ini.Get("airMonitor", "zones").ToString().Split(',');
|
zones = _ini.Get("airMonitor", "zones").ToString().Split(',');
|
||||||
|
@ -63,9 +98,11 @@ namespace IngameScript
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_console.Print($"Found {_zones.Count} zones.");
|
_console.Print($"Found {_zones.Count} zones:");
|
||||||
foreach (AirZone zone in _zones.Values)
|
foreach (KeyValuePair<string, AirZone> kvp in _zones)
|
||||||
{
|
{
|
||||||
|
AirZone zone = kvp.Value;
|
||||||
|
_console.Print(kvp.Key);
|
||||||
_jobs.Add(zone.Monitor());
|
_jobs.Add(zone.Monitor());
|
||||||
}
|
}
|
||||||
Runtime.UpdateFrequency |= UpdateFrequency.Update100;
|
Runtime.UpdateFrequency |= UpdateFrequency.Update100;
|
||||||
|
@ -85,12 +122,42 @@ namespace IngameScript
|
||||||
_console.Print($"Resetting {zone}.");
|
_console.Print($"Resetting {zone}.");
|
||||||
if (_zones.ContainsKey(zone))
|
if (_zones.ContainsKey(zone))
|
||||||
{
|
{
|
||||||
_zones[zone].Triggered = false;
|
_zones[zone].Reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// write diagnostics
|
||||||
|
if (_displays.Count != 0)
|
||||||
|
{
|
||||||
|
_displayBuffer.Clear();
|
||||||
|
_displayBuffer.Append("AIR PRESSURE REPORT\n\n");
|
||||||
|
foreach (AirZone zone in _zones.Values)
|
||||||
|
{
|
||||||
|
_displayBuffer.Append(zone.Name);
|
||||||
|
_displayBuffer.Append(": ");
|
||||||
|
_displayBuffer.Append(zone.Triggered ? "ALARM TRIPPED " : "NOMINAL ");
|
||||||
|
foreach (IMyAirVent vent in zone.Vents)
|
||||||
|
{
|
||||||
|
_displayBuffer.Append((int)(vent.GetOxygenLevel() * 100F));
|
||||||
|
_displayBuffer.Append("% ");
|
||||||
|
}
|
||||||
|
|
||||||
|
_displayBuffer.Append("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
_displayBuffer.Append("\n");
|
||||||
|
_displayBuffer.Append("OXYGEN TANK LEVELS\n");
|
||||||
|
foreach (IMyGasTank tank in _oxygenTanks)
|
||||||
|
{
|
||||||
|
_displayBuffer.Append((int)(tank.FilledRatio * 100));
|
||||||
|
_displayBuffer.Append("% ");
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (IMyTextSurface display in _displays) display.WriteText(_displayBuffer.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
foreach (IEnumerator job in _jobs)
|
foreach (IEnumerator job in _jobs)
|
||||||
{
|
{
|
||||||
if (job.MoveNext()) continue;
|
if (job.MoveNext()) continue;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user