Last active
January 12, 2018 21:05
-
-
Save luvies/fa8e5261a33390a2d7a9f49283ec7345 to your computer and use it in GitHub Desktop.
Liftoff Manager ingame script for Space Engineers
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*-*/ | |
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