Initial SE scripts.
This commit is contained in:
commit
44d161f5c0
258
airlock.cs
Normal file
258
airlock.cs
Normal file
|
@ -0,0 +1,258 @@
|
||||||
|
enum AirlockState {
|
||||||
|
Off,
|
||||||
|
DoorsClosing,
|
||||||
|
Cycling,
|
||||||
|
DoorOpening,
|
||||||
|
Cooldown,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum AirlockLightState {
|
||||||
|
Off,
|
||||||
|
Cycling,
|
||||||
|
Cooldown,
|
||||||
|
Error,
|
||||||
|
}
|
||||||
|
|
||||||
|
string airlockName;
|
||||||
|
IEnumerator<bool> state;
|
||||||
|
float targetOxygenLevel = 0.0F;
|
||||||
|
|
||||||
|
// Blocks we need to track
|
||||||
|
IMyDoor innerDoor;
|
||||||
|
IMyDoor outerDoor;
|
||||||
|
List<IMyLightingBlock> lights;
|
||||||
|
IMyAirVent airVent;
|
||||||
|
IMyAirVent airSensor; // TODO: we don't use this yet
|
||||||
|
IMyGasTank oxygenTank;
|
||||||
|
|
||||||
|
public Program()
|
||||||
|
{
|
||||||
|
airlockName = Me.CustomName.Split(' ')[0];
|
||||||
|
state = null;
|
||||||
|
|
||||||
|
// Find the correct objects
|
||||||
|
InitDoors();
|
||||||
|
InitVents();
|
||||||
|
InitLights();
|
||||||
|
InitOxygen();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitDoors() {
|
||||||
|
List<IMyDoor> onlyDoors = new List<IMyDoor>();
|
||||||
|
GridTerminalSystem.GetBlocksOfType(onlyDoors);
|
||||||
|
foreach (IMyDoor door in onlyDoors) {
|
||||||
|
if (door.CustomName.StartsWith(airlockName)) {
|
||||||
|
if (door.CustomName.Contains("Inner")) {
|
||||||
|
innerDoor = door;
|
||||||
|
}
|
||||||
|
else if (door.CustomName.Contains("Outer")) {
|
||||||
|
outerDoor = door;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (innerDoor != null && outerDoor != null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitVents() {
|
||||||
|
List<IMyAirVent> onlyFans = new List<IMyAirVent>();
|
||||||
|
GridTerminalSystem.GetBlocksOfType(onlyFans);
|
||||||
|
foreach (IMyAirVent vent in onlyFans) {
|
||||||
|
if (vent.CustomName.StartsWith(airlockName)) {
|
||||||
|
if (vent.CustomName.Contains("Main")) {
|
||||||
|
airVent = vent;
|
||||||
|
}
|
||||||
|
else if (vent.CustomName.Contains("Reference")) {
|
||||||
|
airSensor = vent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A global reference vent will be used if we don't have one specific to our airlock.
|
||||||
|
// A specific vent found later will overwrite this assignment.
|
||||||
|
if(vent.CustomName.StartsWith("Airlock Reference") && airSensor == null) {
|
||||||
|
airSensor = vent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitLights() {
|
||||||
|
lights = new List<IMyLightingBlock>();
|
||||||
|
List<IMyLightingBlock> allLights = new List<IMyLightingBlock>();
|
||||||
|
GridTerminalSystem.GetBlocksOfType(allLights);
|
||||||
|
foreach (IMyLightingBlock light in allLights) {
|
||||||
|
if (light.CustomName.StartsWith(airlockName)) {
|
||||||
|
lights.Add(light);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitOxygen() {
|
||||||
|
List<IMyGasTank> allTanks = new List<IMyGasTank>();
|
||||||
|
GridTerminalSystem.GetBlocksOfType(allTanks);
|
||||||
|
foreach (IMyGasTank tank in allTanks) {
|
||||||
|
if (tank.CustomName.StartsWith(airlockName)) {
|
||||||
|
oxygenTank = tank;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Main(string argument, UpdateType updateSource)
|
||||||
|
{
|
||||||
|
if (state == null) {
|
||||||
|
state = CycleAirlock();
|
||||||
|
Runtime.UpdateFrequency = UpdateFrequency.Update1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!state.MoveNext()) {
|
||||||
|
state.Dispose();
|
||||||
|
state = null;
|
||||||
|
Runtime.UpdateFrequency = UpdateFrequency.None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerator<bool> CycleAirlock() {
|
||||||
|
SetLights(AirlockLightState.Cycling);
|
||||||
|
|
||||||
|
CloseDoors();
|
||||||
|
while(!DoorsClosed()) { yield return true; }
|
||||||
|
LockDoors();
|
||||||
|
|
||||||
|
if (!airVent.CanPressurize) {
|
||||||
|
Error("Airlock is not airtight.");
|
||||||
|
yield return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
PressurizeDepressurize();
|
||||||
|
while(!PressureStabilized()) { yield return true; }
|
||||||
|
airVent.Enabled = false;
|
||||||
|
|
||||||
|
OpenDoor();
|
||||||
|
while(!DoorOpened()) { yield return true; }
|
||||||
|
LockDoors();
|
||||||
|
|
||||||
|
// Balance oxygen storage
|
||||||
|
SetLights(AirlockLightState.Cooldown);
|
||||||
|
if (BalanceOxygen()) {
|
||||||
|
while(!OxygenBalanced()) { yield return true; }
|
||||||
|
}
|
||||||
|
airVent.Enabled = false;
|
||||||
|
|
||||||
|
// Cooldown period
|
||||||
|
Runtime.UpdateFrequency = UpdateFrequency.Update100;
|
||||||
|
yield return true;
|
||||||
|
Runtime.UpdateFrequency = UpdateFrequency.Update1;
|
||||||
|
|
||||||
|
SetLights(AirlockLightState.Off);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CloseDoors() {
|
||||||
|
Echo("DEBUG: Closing Doors");
|
||||||
|
|
||||||
|
// close the doors
|
||||||
|
innerDoor.Enabled = true;
|
||||||
|
outerDoor.Enabled = true;
|
||||||
|
innerDoor.CloseDoor();
|
||||||
|
outerDoor.CloseDoor();
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool DoorsClosed() {
|
||||||
|
return innerDoor.Status == DoorStatus.Closed && outerDoor.Status == DoorStatus.Closed;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PressurizeDepressurize() {
|
||||||
|
Echo("DEBUG: Cycling");
|
||||||
|
|
||||||
|
// toggle the current state
|
||||||
|
airVent.Depressurize = !airVent.Depressurize;
|
||||||
|
airVent.Enabled = true;
|
||||||
|
|
||||||
|
// When depressurizing, check the external pressure and only depressurize to that value.
|
||||||
|
// TODO: test this for floating point errors
|
||||||
|
if (airVent.Depressurize && airSensor != null) {
|
||||||
|
targetOxygenLevel = airSensor.GetOxygenLevel();
|
||||||
|
Echo($"Set depressurization target to {targetOxygenLevel}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: this should check for depressurizing to the *reference* amount
|
||||||
|
private bool PressureStabilized() {
|
||||||
|
return ((airVent.Depressurize && airVent.GetOxygenLevel() <= targetOxygenLevel) ||
|
||||||
|
(!airVent.Depressurize && airVent.Status == VentStatus.Pressurized));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open the appropriate door based on pressure state.
|
||||||
|
private void OpenDoor() {
|
||||||
|
Echo("DEBUG: Opening Door");
|
||||||
|
|
||||||
|
if (airVent.Status == VentStatus.Pressurized) {
|
||||||
|
innerDoor.Enabled = true;
|
||||||
|
innerDoor.OpenDoor();
|
||||||
|
} else {
|
||||||
|
outerDoor.Enabled = true;
|
||||||
|
outerDoor.OpenDoor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool DoorOpened() {
|
||||||
|
return innerDoor.Status == DoorStatus.Open || outerDoor.Status == DoorStatus.Open;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns false if we are in a state where we can't or don't need to balance
|
||||||
|
private bool BalanceOxygen() {
|
||||||
|
if (innerDoor.Status == DoorStatus.Closed || outerDoor.Status == DoorStatus.Open || OxygenBalanced()) { return false; }
|
||||||
|
|
||||||
|
Echo("DEBUG: Balancing Oxygen Tank");
|
||||||
|
|
||||||
|
// Configure the vent to suck in Oxygen.
|
||||||
|
airVent.Depressurize = true;
|
||||||
|
airVent.Enabled = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool OxygenBalanced() {
|
||||||
|
return oxygenTank.FilledRatio > 0.25;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: blinkenlights are unsatisfying right now...
|
||||||
|
private void SetLights(AirlockLightState lightState) {
|
||||||
|
float blinkLength = 1.0F;
|
||||||
|
float blinkInterval = 0.0F;
|
||||||
|
Color color = Color.Red;
|
||||||
|
|
||||||
|
switch(lightState) {
|
||||||
|
case AirlockLightState.Off:
|
||||||
|
color = Color.Green;
|
||||||
|
break;
|
||||||
|
case AirlockLightState.Cycling:
|
||||||
|
blinkInterval = 1.0F;
|
||||||
|
blinkLength = 0.75F;
|
||||||
|
break;
|
||||||
|
case AirlockLightState.Cooldown:
|
||||||
|
color = Color.Yellow;
|
||||||
|
break;
|
||||||
|
case AirlockLightState.Error:
|
||||||
|
// the defaults already set this correctly
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (IMyLightingBlock light in lights) {
|
||||||
|
light.Enabled = true;
|
||||||
|
light.BlinkIntervalSeconds = blinkInterval;
|
||||||
|
light.BlinkLength = blinkLength;
|
||||||
|
light.Color = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LockDoors() {
|
||||||
|
innerDoor.Enabled = false;
|
||||||
|
outerDoor.Enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Error(string error) {
|
||||||
|
Echo(error);
|
||||||
|
SetLights(AirlockLightState.Error);
|
||||||
|
}
|
88
docking.cs
Normal file
88
docking.cs
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
// Docking controller script; handles docking and undocking.
|
||||||
|
// Specifically, when you activate the script it will:
|
||||||
|
// * Connect any Connectors whose names start with "Docking Port" that are ready to connect.
|
||||||
|
// * Turn off all engines.
|
||||||
|
// * Set all O2 and Hydrogen tanks to Stockpile.
|
||||||
|
// * Set all batteries to Recharge.
|
||||||
|
//
|
||||||
|
// When you activate the script with "-undock" it will reverse all of these actions.
|
||||||
|
//
|
||||||
|
// TODO: None of the below switches work yet.
|
||||||
|
// You can selectively disable some functionality with switches.
|
||||||
|
// * "-no-refuel" to disable refueling
|
||||||
|
// * "-no-recharge" to disable battery recharge
|
||||||
|
// (batteries will be left in whatever state they are already in)
|
||||||
|
|
||||||
|
MyCommandLine cli;
|
||||||
|
|
||||||
|
List<IMyShipConnector> dockingPorts;
|
||||||
|
List<IMyThrust> thrusters;
|
||||||
|
List<IMyBatteryBlock> batteries;
|
||||||
|
List<IMyGasTank> tanks;
|
||||||
|
|
||||||
|
public void Program() {
|
||||||
|
cli = new MyCommandLine();
|
||||||
|
|
||||||
|
dockingPorts = new List<IMyShipConnector>();
|
||||||
|
List<IMyShipConnector> allConnectors = new List<IMyShipConnector>();
|
||||||
|
foreach(IMyShipConnector connector in allConnectors) {
|
||||||
|
if (connector.CustomName.StartsWith("Docking Port")) {
|
||||||
|
dockingPorts.Add(connector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
thrusters = new List<IMyThrust>();
|
||||||
|
GridTerminalSystem.GetBlocksOfType(thrusters);
|
||||||
|
|
||||||
|
batteries = new List<IMyBatteryBlock>();
|
||||||
|
GridTerminalSystem.GetBlocksOfType(batteries);
|
||||||
|
|
||||||
|
tanks = new List<IMyGasTank>();
|
||||||
|
GridTerminalSystem.GetBlocksOfType(tanks);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Main(string argument, UpdateType updateSource) {
|
||||||
|
cli.TryParse(argument);
|
||||||
|
if (cli.Switch("undock")) Undock();
|
||||||
|
else Dock();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Dock() {
|
||||||
|
foreach (IMyShipConnector dockingPort in dockingPorts) {
|
||||||
|
if (dockingPort.Status == MyShipConnectorStatus.Connectable) {
|
||||||
|
dockingPort.Connect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (IMyThrust thruster in thrusters) {
|
||||||
|
thruster.Enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (IMyBatteryBlock battery in batteries) {
|
||||||
|
battery.ChargeMode = ChargeMode.Recharge;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (IMyGasTank tank in tanks) {
|
||||||
|
tank.Stockpile = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Undock() {
|
||||||
|
foreach (IMyBatteryBlock battery in batteries) {
|
||||||
|
battery.ChargeMode = ChargeMode.Recharge;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (IMyGasTank tank in tanks) {
|
||||||
|
tank.Stockpile = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (IMyThrust thruster in thrusters) {
|
||||||
|
thruster.Enabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (IMyShipConnector dockingPort in dockingPorts) {
|
||||||
|
if (dockingPort.Status == MyShipConnectorStatus.Connected) {
|
||||||
|
dockingPort.Disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
130
maintenance_panels.cs
Normal file
130
maintenance_panels.cs
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user