Skip to content

Instantly share code, notes, and snippets.

@luvies
Last active January 12, 2018 21:05
Show Gist options
  • Save luvies/fa8e5261a33390a2d7a9f49283ec7345 to your computer and use it in GitHub Desktop.
Save luvies/fa8e5261a33390a2d7a9f49283ec7345 to your computer and use it in GitHub Desktop.
Liftoff Manager ingame script for Space Engineers
/*-*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Sandbox.Common;
using Sandbox.Common.ObjectBuilders;
using Sandbox.Definitions;
using Sandbox.Engine;
using Sandbox.ModAPI.Ingame;
using Sandbox.ModAPI.Interfaces;
using Sandbox.Game;
using SpaceEngineers.Game.ModAPI.Ingame;
using VRageMath;
namespace Scripts.LiftoffMangaer // change 'BaseProgram' to the name of the script itself to stop accidental cross-referencing
{
class Program : Sandbox.ModAPI.IMyGridProgram // class name needs to be 'Program' in order to satisfy constructor method
{
// These are members implemented using NotImplementedException
// in order to satisfy VS in extending the Sandbox.ModAPI.IMyGridProgram
// interface (which is where all programming block programs extend from)
public Action<string> Echo { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public TimeSpan ElapsedTime { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public IMyGridTerminalSystem GridTerminalSystem { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public bool HasMainMethod => throw new NotImplementedException();
public bool HasSaveMethod => throw new NotImplementedException();
public IMyProgrammableBlock Me { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public IMyGridProgramRuntimeInfo Runtime { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public string Storage { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public void Save() => throw new NotImplementedException();
public void Main(string argument) => throw new NotImplementedException();
//public void Main(string argument, UpdateType updateSource) => throw new NotImplementedException();
/* ===== Additional info =====
* public string IMyTerminalBlock.CustomData -> synced and saved custom data that can be edited via terminal
*
* Programs extend from
* Sandbox.ModAPI.IMyGridProgram
*
* Solar power output contained in
* IMyTerminalBlock.DetailedInfo
*
* Actions can be triggered via
* IMyTerminalBlock.ApplyAction(string action)
*
* Use 'Right Click -> Peek Definition' to see what you can do with an inferface (the documentation is lacking to say the least)
*
* The following is an extention class the IMyTerminalBlock interface
* Sandbox.ModAPI.Ingame.TerminalBlockExtentions
*
* Runtime.UpdateFrequency allows you to automate the running of the script without using timer
* blocks. If you are monitoring something (or doing something similar that requires repeated calls)
* then use this rather than a timer block.
*/
/*-*/
/* Script derived mainly from
* http://steamcommunity.com/sharedfiles/filedetails/?id=561944966
* with help from
* http://steamcommunity.com/sharedfiles/filedetails/?id=637302443
*/
// <===> Edit the following variables <===>
// === settings ===
// The main thruster group to use for acsending (required)
const string mainThrustersGroup = "P-Hopper - Small - Thrusters - Up";
// the LCD panel to output info to (optional)
const string lcdDisplay = "Text panel - Liftoff Manager";
// the maximum speed to run at (if you are using a speed mod
// it should adjust automatically, however you can set it manually
double maxSpeed = 100;
// whether to enforce the max speed setting or use the world
// maximum speed (i.e. if false, maxSpeed will be automatically
// set to the world speed)
bool forceMaxSpeed = false;
// the minimum gravity threshold before the thrusters cut off and
// dampeners cut in (in G)
double gravityThreshold = 0.076;
// the minimum speed to run at
const double minSpeedTolerance = 0.98;
// the maximum speed to run at
const double maxSpeedTolerance = 0.999;
// if max speed is below this percentage, full thrusters are used
const double minTweakSpeed = 0.5;
// === other config ===
// thrust override percent decrease per run
const float decreaseOverrideRate = 0.0014f; // default: 1.4%
// thrust override percent increase per run
const float increaseOverrideRate = 0.0005f; // default: 0.5%
// minimum thrust override to stop dampeners
const float minOverride = 0.01f; // default: 1%
// <===> leave everything below alone <===>
/*m*/
const double earthG = 9.81;
public void Main(string argument, UpdateType updateSource)
{
// setup base vars
StringBuilder output = new StringBuilder();
IMyTextPanel outputLcd;
// get a controller to work with
List<IMyShipController> controllers = new List<IMyShipController>();
GridTerminalSystem.GetBlocksOfType(controllers);
if (controllers.Count == 0)
{
Echo("No controller found, aborting liftoff...");
return;
}
IMyShipController controller = controllers[0];
// get up thrusters
IMyBlockGroup thrustGroup = GridTerminalSystem.GetBlockGroupWithName(mainThrustersGroup);
if (thrustGroup == null)
{
Echo("Unable to find thruster group, aborting liftoff...");
return;
}
List<IMyThrust> thrusters = new List<IMyThrust>();
thrustGroup.GetBlocksOfType(thrusters);
if (thrusters.Count == 0)
{
Echo("No thrusters in specified group, aborting liftoff...");
return;
}
// process argument
if (argument.ToLower() == "stop")
{
Echo("Liftoff aborted");
outputLcd = GridTerminalSystem.GetBlockWithName(lcdDisplay) as IMyTextPanel;
outputLcd?.WritePublicText("Liftoff Aborted");
Runtime.UpdateFrequency = UpdateFrequency.None;
SetThrustersOverridePercent(thrusters, 0, true);
return;
}
// do main liftoff process
double currentG = controller.GetNaturalGravity().Length() / earthG;
if (currentG <= gravityThreshold)
{
// we are beyond gravity limit, so are done
WriteOutput(output, "Minimum gravity threshold achieved!");
WriteOutput(output, "Liftoff complete");
Runtime.UpdateFrequency = UpdateFrequency.None;
SetThrustersOverridePercent(thrusters, 0, true);
}
else
{
// we are inside gravity limit, and so need to do takeoff
WriteOutput(output, "Current G: {0}", Math.Round(currentG, 2));
// make ourselves update to monitor speed and gravity level
Runtime.UpdateFrequency = UpdateFrequency.Update1; // might increase rate for better accuracy
// get status vars
double speed = controller.GetShipSpeed();
double angle = Math.Acos(
Vector3D.Dot(Vector3D.Normalize(controller.GetNaturalGravity()),
Vector3D.Normalize(-controller.GetShipVelocities().LinearVelocity))) * 180 / Math.PI;
WriteOutput(output, "Current Speed: {0} m/s", Math.Round(speed, 1));
WriteOutput(output, "Current Angle Deviation: {0}°", Math.Round(angle, 1));
if (speed < maxSpeed * minTweakSpeed)
SetThrustersOverridePercent(thrusters, 1);
else if (speed < maxSpeed * minSpeedTolerance)
SetThrustersOverridePercent(thrusters, GetThrusterOverridePercent(thrusters) + increaseOverrideRate);
else if (speed > maxSpeed && !forceMaxSpeed) // if we are exceeding the speed limt, then a speed limit mod is being used
maxSpeed = speed;
else if (speed > maxSpeed * maxSpeedTolerance) // otherwise we are at max speed
SetThrustersOverridePercent(thrusters, GetThrusterOverridePercent(thrusters) - decreaseOverrideRate);
WriteOutput(output, "Thrusters Output: {0}%", Math.Round(GetThrusterOverridePercent(thrusters) * 100));
}
// output information for this run
string fullOutput = output.ToString();
Echo(fullOutput);
outputLcd = GridTerminalSystem.GetBlockWithName(lcdDisplay) as IMyTextPanel;
outputLcd?.WritePublicText(fullOutput);
}
void WriteOutput(StringBuilder output, string fmt, params object[] args)
{
output.Append(string.Format(fmt, args));
output.Append('\n');
}
float GetThrusterOverridePercent(List<IMyThrust> thrusters)
{
return thrusters[0].ThrustOverridePercentage;
}
void SetThrustersOverridePercent(List<IMyThrust> thrusters, float percent, bool force = false)
{
if (percent < minOverride && !force)
percent = minOverride;
else if (percent > 1)
percent = 1;
for (int i = 0; i < thrusters.Count; i++)
thrusters[i].ThrustOverridePercentage = percent;
}
/*m*/
/*-*/
}
}
/*-*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment