// 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 state; List 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(); List allHinges = new List(); 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 OpenPanels() { Echo("Opening panels."); foreach (Panel panel in panels) { panel.OpenPanel(); } return MonitorPanels(); } private IEnumerator ClosePanels() { Echo("Closing panels."); foreach (Panel panel in panels) { panel.ClosePanel(); } return MonitorPanels(); } private IEnumerator 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; } }