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