space_engineers/maintenance_panels.cs
2025-02-06 19:02:13 -05:00

131 lines
3.8 KiB
C#

// Script for opening maintence panels on a ship.
//
// Currently this simply opens and closes *all* of the panels attached to hinges
// whose names start with "Maintenance". Default behavior is to open.
// Pass the argument -close to close the panels.
//
// By default "open" is assumed to be 90 degrees and "closed" is assumed to be 0 degrees.
// Each hinge can have its behavior configured via custom data. A sample config
// (with the default values):
//
// OpenAngle=90
// ClosedAngle=0
// Velocity=5
MyCommandLine cli;
IEnumerator<bool> state;
List<Panel> panels;
public class Panel {
public Panel(IMyMotorStator hinge) {
Hinge = hinge;
ParseConfig();
}
public void OpenPanel() {
Hinge.RotorLock = false;
TargetAngle = OpenAngle;
Hinge.RotateToAngle(MyRotationDirection.AUTO, TargetAngle, Velocity);
}
public void ClosePanel() {
Hinge.RotorLock = false;
TargetAngle = ClosedAngle;
Hinge.RotateToAngle(MyRotationDirection.AUTO, TargetAngle, Velocity);
}
// Call this function every tick after OpenPanel or ClosePanel.
// It will return true when the panel has finished moving.
public bool Monitor() {
if (Math.Abs(Hinge.Angle - TargetAngle) < 0.01) {
Hinge.RotorLock = true;
}
return Hinge.RotorLock;
}
private IMyMotorStator Hinge { get; set; }
private float TargetAngle { get; set; }
private float OpenAngle { get; set; } = 90F;
private float ClosedAngle { get; set; } = 0F;
private float Velocity { get; set; } = 5F;
private void ParseConfig() {
string[] lines = Hinge.CustomData.Split('\n');
foreach (string line in lines) {
string[] tokens = line.Split('=');
if (tokens.Length != 2) continue;
switch(tokens[0]) {
case "OpenAngle":
OpenAngle = float.Parse(tokens[1]);
break;
case "ClosedAngle":
ClosedAngle = float.Parse(tokens[1]);
break;
case "Velocity":
Velocity = float.Parse(tokens[1]);
break;
}
}
}
}
public Program() {
cli = new MyCommandLine();
state = null;
panels = new List<Panel>();
List<IMyMotorStator> allHinges = new List<IMyMotorStator>();
foreach(IMyMotorStator hinge in allHinges) {
if (hinge.CustomName.StartsWith("Maintenance")) {
panels.Add(new Panel(hinge));
}
}
Echo($"Found {panels.Length} panels.");
}
public void Main(string argument, UpdateType updateSource) {
if (state == null) {
cli.TryParse(argument);
if (cli.Switch("close")) state = ClosePanels();
else state = OpenPanels();
Runtime.UpdateFrequency = UpdateFrequency.Update1;
return;
}
if (!state.MoveNext()) {
state.Dispose();
state = null;
Runtime.UpdateFrequency = UpdateFrequency.None;
}
}
private IEnumerator<bool> OpenPanels() {
Echo("Opening panels.");
foreach (Panel panel in panels) {
panel.OpenPanel();
}
return MonitorPanels();
}
private IEnumerator<bool> ClosePanels() {
Echo("Closing panels.");
foreach (Panel panel in panels) {
panel.ClosePanel();
}
return MonitorPanels();
}
private IEnumerator<bool> MonitorPanels() {
while (true) {
Echo("Monitoring panels.");
bool done = true; // assume we've finished, then falsify it below
foreach (Panel panel in panels) {
if (!panel.Monitor()) done = false;
}
if (done) yield break;
yield return true;
}
}