145 lines
4.4 KiB
C#
145 lines
4.4 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();
|
|
}
|
|
|
|
// For these two functions, IMyMotorStator.Angle reports radians, but
|
|
// IMyMotorStator.RotateToAngle() expects degrees...
|
|
public void OpenPanel() {
|
|
Hinge.RotorLock = false;
|
|
TargetAngle = DegToRad(OpenAngle);
|
|
Hinge.RotateToAngle(MyRotationDirection.AUTO, OpenAngle, Velocity);
|
|
}
|
|
|
|
public void ClosePanel() {
|
|
Hinge.RotorLock = false;
|
|
TargetAngle = DegToRad(ClosedAngle);
|
|
Hinge.RotateToAngle(MyRotationDirection.AUTO, ClosedAngle, 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.001) {
|
|
Hinge.RotorLock = true;
|
|
}
|
|
return Hinge.RotorLock;
|
|
}
|
|
|
|
// TODO: these are public for debugging
|
|
public IMyMotorStator Hinge { get; set; }
|
|
public 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;
|
|
}
|
|
}
|
|
}
|
|
|
|
// TODO: a utility class or function would be lovely...
|
|
// In general, the encapsulation feels a little screwy here.
|
|
private float DegToRad(float degrees) {
|
|
return degrees * ((float)Math.PI / 180F);
|
|
}
|
|
}
|
|
|
|
public Program() {
|
|
cli = new MyCommandLine();
|
|
state = null;
|
|
|
|
panels = new List<Panel>();
|
|
List<IMyMotorStator> allHinges = new List<IMyMotorStator>();
|
|
GridTerminalSystem.GetBlocksOfType(allHinges);
|
|
foreach(IMyMotorStator hinge in allHinges) {
|
|
if (hinge.CustomName.StartsWith("Maintenance")) {
|
|
panels.Add(new Panel(hinge));
|
|
}
|
|
}
|
|
|
|
Echo($"Found {panels.Count} 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()) {
|
|
Echo("Operation Complete.");
|
|
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()) {
|
|
Echo($"{panel.TargetAngle} {panel.Hinge.Angle}");
|
|
done = false;
|
|
}
|
|
}
|
|
if (done) yield break;
|
|
yield return true;
|
|
}
|
|
}
|