Whiplash141

Whip's Gravity Drive Manager v12

Apr 26th, 2017
288
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 16.79 KB | None | 0 0
  1.  
  2. /*
  3. /// Whip's Directional Gravity Drive Control Script v12 - 8/2/17 ///
  4. ________________________________________________
  5. Description:
  6.  
  7.     This code allows you to control a gravity drive through normal movement keys.
  8.     The setup is INCREDIBLY simple!
  9.  
  10.     DISCLAIMER: This code is NOT made for planerary flight as grav drives do not work in natural gravity.
  11. ________________________________________________
  12. How do I use this?
  13.  
  14.     1) Place this program on your main grid (the grid your control seat is on)
  15.  
  16.     2) Make a timer block with actions:
  17.     - "Run" this program with NO ARGUMENT
  18.     - "Trigger Now" itself
  19.     - "Start" itself
  20.  
  21.     3) Make a group with all of your gravity drive artificial masses and gravity gens. Name it "Gravity Drive"
  22.  
  23.     4) Trigger the timer
  24.  
  25.     5) Enjoy!
  26. ________________________________________________
  27. Arguments
  28.  
  29.     on : Turns grav drive on
  30.     off : Turns grav drive off
  31.     toggle : toggles grav drive
  32.     dampeners_on: turns gravity dampeners on
  33.     dampeners_off: turns gravity dampeners off
  34.     dampeners_toggle: toggles gravity dampeners
  35. ________________________________________________
  36. Author's Notes
  37.  
  38.     This code was written pon request of my friend Avalash for his big cool carrier thing. I've decided to polish this code
  39.     and release it to the public. Leave any questions, comments, or converns on the workshop page!
  40.  
  41. - Whiplash141
  42. */
  43.  
  44. const string gravityDriveGroupName = "Gravity Drive";
  45. //place all gravity drive generators and masses in this group
  46.  
  47. float gravityDriveDampenerScalingFactor = 0.1f;
  48. //larger values will quicken the dampening using gravity gens but will also risk causing oscillations
  49. //The lighter your ship, the smaller this should be
  50.  
  51. double speedThreshold = 0.01;
  52. //Speed at which the code will stop using gravity drives. Zero means that
  53. //the drive will never turn off (useful for ships with no thrusters)
  54.  
  55. bool useGyrosToStabilize = true;
  56. //If the script will override gyros to try and combat torque
  57.  
  58. bool useGravityDriveAsInertialDampeners = true;
  59. //If the code should treat the gravity drive as an inertial dampeners.
  60. //If no thrusters are found on the ship, this variable is used to determine
  61. //if inertial dampeners should be turned on/off.
  62.  
  63. bool enableDampenersWhenNotControlled = true;
  64. //This will force gravity dampeners on if no one is controlling the ship
  65.  
  66. //-------------------------------------------------------------------------
  67. //============ NO TOUCH BELOW HERE!!! =====================================
  68. //-------------------------------------------------------------------------
  69.  
  70. const double updatesPerSecond = 10;
  71. const double timeMaxCycle = 1 / updatesPerSecond;
  72. //const float stepRatio = 0.1f; //this is the ratio of the max acceleration to add each code cycle
  73. double timeCurrentCycle = 0;
  74.  
  75. const double refreshInterval = 10;
  76. double refreshTime = 141;
  77.  
  78. bool turnOn = true;
  79. bool isSetup = false;
  80.  
  81. void Main(string arg)
  82. {
  83.     switch (arg.ToLower())
  84.     {
  85.         case "on":
  86.             turnOn = true;
  87.             break;
  88.  
  89.         case "off":
  90.             turnOn = false;
  91.             break;
  92.  
  93.         case "toggle":
  94.             turnOn = !turnOn; //switches boolean value
  95.             break;
  96.            
  97.         case "dampeners_on":
  98.             useGravityDriveAsInertialDampeners = true;
  99.             break;
  100.            
  101.         case "dampeners_off":
  102.             useGravityDriveAsInertialDampeners = false;
  103.             break;
  104.            
  105.         case "dampeners_toggle":
  106.             useGravityDriveAsInertialDampeners = !useGravityDriveAsInertialDampeners;
  107.             break;
  108.     }
  109.  
  110.     timeCurrentCycle += Runtime.TimeSinceLastRun.TotalSeconds;
  111.     refreshTime += Runtime.TimeSinceLastRun.TotalSeconds;
  112.     try
  113.     {
  114.         if (!isSetup || refreshTime >= refreshInterval)
  115.         {
  116.             isSetup = GrabBlocks();
  117.             refreshTime = 0;
  118.         }
  119.  
  120.         if (!isSetup)
  121.             return;
  122.  
  123.         if (timeCurrentCycle >= timeMaxCycle)
  124.         {
  125.             Echo("WMI Gravity Drive Manager... " + RunningSymbol());
  126.            
  127.             Echo($"Next refresh in {Math.Max(refreshInterval - refreshTime, 0):N0} seconds");
  128.  
  129.             if (turnOn)
  130.                 Echo("\nGravity Drive is Enabled");
  131.             else
  132.                 Echo("\nGravity Drive is Disabled");
  133.            
  134.             if (useGravityDriveAsInertialDampeners)
  135.                 Echo("\nGravity Dampeners Enabled");
  136.             else
  137.                 Echo("\nGravity Dampeners Disabled");
  138.  
  139.             Echo($"\nGravity Drive Stats:\n Artificial Masses: {artMasses.Count}\n Gravity Generators:\n >Forward: {fowardGens.Count}\n >Backward: {backwardGens.Count}\n >Left: {leftGens.Count}\n >Right: {rightGens.Count}\n >Up: {upGens.Count}\n >Down: {downGens.Count}\n >Other: {otherGens.Count}");
  140.            
  141.             Echo($"\nGyro Stabilization: {useGyrosToStabilize}\n Gyro count: {gyros.Count}");
  142.  
  143.             ManageGravDrive(turnOn);
  144.             timeCurrentCycle = 0;
  145.  
  146.             runningSymbolVariant++;
  147.         }
  148.     }
  149.     catch
  150.     {
  151.         isSetup = false;
  152.     }
  153. }
  154.  
  155. //Whip's Running Symbol Method v6
  156. int runningSymbolVariant = 0;
  157. string RunningSymbol()
  158. {
  159.     string strRunningSymbol = "";
  160.  
  161.     if (runningSymbolVariant == 0)
  162.         strRunningSymbol = "|";
  163.     else if (runningSymbolVariant == 1)
  164.         strRunningSymbol = "/";
  165.     else if (runningSymbolVariant == 2)
  166.         strRunningSymbol = "--";
  167.     else if (runningSymbolVariant == 3)
  168.     {
  169.         strRunningSymbol = "\\";
  170.         runningSymbolVariant = 0;
  171.     }
  172.  
  173.     return strRunningSymbol;
  174. }
  175.  
  176.  
  177. List<IMyShipController> shipControllers = new List<IMyShipController>();
  178. List<IMyGravityGenerator> gravityGens = new List<IMyGravityGenerator>();
  179. List<IMyGravityGenerator> upGens = new List<IMyGravityGenerator>();
  180. List<IMyGravityGenerator> downGens = new List<IMyGravityGenerator>();
  181. List<IMyGravityGenerator> leftGens = new List<IMyGravityGenerator>();
  182. List<IMyGravityGenerator> rightGens = new List<IMyGravityGenerator>();
  183. List<IMyGravityGenerator> fowardGens = new List<IMyGravityGenerator>();
  184. List<IMyGravityGenerator> backwardGens = new List<IMyGravityGenerator>();
  185. List<IMyGravityGenerator> otherGens = new List<IMyGravityGenerator>();
  186. List<List<IMyGravityGenerator>> gravityList = new List<List<IMyGravityGenerator>>();
  187. List<IMyVirtualMass> artMasses = new List<IMyVirtualMass>();
  188. List<IMyThrust> onGridThrust = new List<IMyThrust>();
  189. List<IMyGyro> gyros = new List<IMyGyro>();
  190. IMyBlockGroup gravityDriveGroup = null;
  191.  
  192. bool GrabBlocks()
  193. {
  194.     shipControllers.Clear();
  195.     gravityGens.Clear();
  196.     upGens.Clear();
  197.     downGens.Clear();
  198.     leftGens.Clear();
  199.     rightGens.Clear();
  200.     fowardGens.Clear();
  201.     backwardGens.Clear();
  202.     otherGens.Clear();
  203.     artMasses.Clear();
  204.     gravityList.Clear();
  205.     gyros.Clear();
  206.     gravityDriveGroup = null;
  207.  
  208.     GridTerminalSystem.GetBlocksOfType(shipControllers, block => block.CubeGrid == Me.CubeGrid); //makes sure controller is on same grid
  209.     GridTerminalSystem.GetBlocksOfType(onGridThrust, block => block.CubeGrid == Me.CubeGrid);
  210.     GridTerminalSystem.GetBlocksOfType(gyros, block => block.CubeGrid == Me.CubeGrid);
  211.     gravityDriveGroup = GridTerminalSystem.GetBlockGroupWithName(gravityDriveGroupName);
  212.  
  213.     #region block_check
  214.     bool critFailure = false;
  215.     if (gravityDriveGroup == null)
  216.     {
  217.         Echo($"Critical Error: No group named {gravityDriveGroupName} was found");
  218.         critFailure = true;
  219.     }
  220.     else
  221.     {
  222.         gravityDriveGroup.GetBlocksOfType(artMasses);
  223.         gravityDriveGroup.GetBlocksOfType(gravityGens, x => x.CubeGrid == Me.CubeGrid);
  224.         gravityDriveGroup.GetBlocksOfType(otherGens, x => x.CubeGrid != Me.CubeGrid);
  225.     }
  226.  
  227.     if (artMasses.Count == 0)
  228.     {
  229.         Echo($"Critical Error: No artificial masses found in the {gravityDriveGroupName} group");
  230.         critFailure = true;
  231.     }
  232.  
  233.     if (gravityGens.Count == 0)
  234.     {
  235.         Echo($"Critical Error: No gravity generators found in the {gravityDriveGroupName} group");
  236.         critFailure = true;
  237.     }
  238.  
  239.     if (shipControllers.Count == 0)
  240.     {
  241.         Echo("Critical Error: No ship controllers found on the grid");
  242.         critFailure = true;
  243.     }
  244.     else
  245.     {
  246.         var controller = shipControllers[0];
  247.         foreach (var block in gravityGens)
  248.         {
  249.             if (controller.WorldMatrix.Forward == block.WorldMatrix.Down)
  250.                 fowardGens.Add(block);
  251.             else if (controller.WorldMatrix.Backward == block.WorldMatrix.Down)
  252.                 backwardGens.Add(block);
  253.             else if (controller.WorldMatrix.Left == block.WorldMatrix.Down)
  254.                 leftGens.Add(block);
  255.             else if (controller.WorldMatrix.Right == block.WorldMatrix.Down)
  256.                 rightGens.Add(block);
  257.             else if (controller.WorldMatrix.Up == block.WorldMatrix.Down)
  258.                 upGens.Add(block);
  259.             else if (controller.WorldMatrix.Down == block.WorldMatrix.Down)
  260.                 downGens.Add(block);
  261.         }
  262.  
  263.         gravityList.Add(fowardGens);
  264.         gravityList.Add(backwardGens);
  265.         gravityList.Add(leftGens);
  266.         gravityList.Add(rightGens);
  267.         gravityList.Add(upGens);
  268.         gravityList.Add(downGens);
  269.     }
  270.  
  271.     return !critFailure;
  272.     #endregion
  273. }
  274.  
  275. //Does the job well enough lol
  276. void OverrideGyros(bool overrideOn)
  277. {
  278.     foreach (var block in gyros)
  279.     {
  280.         if (overrideOn)
  281.         {
  282.             block.Yaw = 0f;
  283.             block.Pitch = 0f;
  284.             block.Roll = 0f;
  285.             block.GyroOverride = true;
  286.             block.GyroPower = 100f; //im assuming this is a percentage
  287.         }
  288.         else
  289.             block.GyroOverride = false;
  290.     }
  291. }
  292.  
  293.  
  294. void ManageGravDrive(bool turnOn)
  295. {
  296.     IMyShipController reference = GetControlledShipController(shipControllers);
  297.    
  298.     bool hasPilot = reference != null;
  299.    
  300.     if (!hasPilot)
  301.     {
  302.         reference = shipControllers[0];
  303.     }
  304.  
  305.     //Desired travel vector construction
  306.     var referenceMatrix = reference.WorldMatrix;
  307.     var inputVec = reference.MoveIndicator; //raw input vector
  308.     var rollVec = reference.RollIndicator;
  309.     var mouseInputVec = reference.RotationIndicator;
  310.    
  311.     if (useGyrosToStabilize)
  312.     {
  313.         //This method was derived from Rod-Serling's The One Gravity Drive Script
  314.         //Much simpler than the Differential Equations I was trying to solve
  315.         OverrideGyros(rollVec == 0 && mouseInputVec.LengthSquared() == 0 && turnOn);
  316.     }
  317.    
  318.     var desiredDirection = referenceMatrix.Backward * inputVec.Z + referenceMatrix.Right * inputVec.X + referenceMatrix.Up * inputVec.Y; //world relative input vector
  319.     if (desiredDirection.LengthSquared() > 0)
  320.     {
  321.         desiredDirection = Vector3D.Normalize(desiredDirection);
  322.     }
  323.  
  324.     var velocityVec = reference.GetShipVelocities().LinearVelocity;
  325.    
  326.     bool hasThrust = true;
  327.     if (onGridThrust.Count == 0)
  328.         hasThrust = false;
  329.  
  330.     bool dampenersOn = hasThrust ? useGravityDriveAsInertialDampeners ? reference.DampenersOverride : false : useGravityDriveAsInertialDampeners;
  331.    
  332.  
  333.     if ((velocityVec.LengthSquared() <= speedThreshold * speedThreshold && Vector3D.IsZero(desiredDirection))|| !turnOn )
  334.     {
  335.         ToggleMass(artMasses, false);
  336.         ToggleDirectionalGravity(desiredDirection, velocityVec, false, dampenersOn);
  337.     }
  338.     else if (!hasPilot && enableDampenersWhenNotControlled)
  339.     {
  340.         ToggleMass(artMasses, true); //default all masses to turn on
  341.         ToggleDirectionalGravity(Vector3D.Zero, velocityVec, turnOn, true);
  342.     }
  343.     else
  344.     {
  345.         ToggleMass(artMasses, true); //default all masses to turn on
  346.         ToggleDirectionalGravity(desiredDirection, velocityVec, turnOn, dampenersOn);
  347.     }
  348. }
  349.  
  350. IMyShipController GetControlledShipController(List<IMyShipController> SCs)
  351. {
  352.     foreach (IMyShipController thisController in SCs)
  353.     {
  354.         if (thisController.IsUnderControl && thisController.CanControlShip)
  355.             return thisController;
  356.     }
  357.  
  358.     return null;
  359. }
  360.  
  361. void ToggleDirectionalGravity(Vector3D direction, Vector3D velocityVec, bool turnOn, bool dampenersOn = true)
  362. {
  363.     //Handle on grid grav gens
  364.     foreach (var list in gravityList)
  365.     {
  366.         if (list.Count == 0)
  367.             continue;
  368.  
  369.         var referenceGen = list[0];
  370.  
  371.         if (turnOn)
  372.         {
  373.             double gravThrustRatio = referenceGen.WorldMatrix.Down.Dot(direction);
  374.             double gravDampingRatio;
  375.  
  376.             gravDampingRatio = referenceGen.WorldMatrix.Up.Dot(velocityVec);
  377.  
  378.             //list do this
  379.             SetGravityAcceleration(list, (float)gravThrustRatio * 9.81f);
  380.             //referenceGen.SetValue("Gravity", (float)gravThrustRatio * 9.81f);
  381.             SetGravityPower(list, true);
  382.             //referenceGen.SetValue("OnOff", true);
  383.  
  384.             if (dampenersOn)
  385.             {
  386.                 double targetOverride = 0;
  387.  
  388.                 if (Math.Abs(gravDampingRatio) < 1)
  389.                     targetOverride = gravDampingRatio * gravityDriveDampenerScalingFactor;
  390.                 else
  391.                     targetOverride = Math.Sign(gravDampingRatio) * gravDampingRatio * gravDampingRatio * gravityDriveDampenerScalingFactor;
  392.  
  393.                 if (targetOverride < 0 && gravThrustRatio <= 0 && Math.Abs(targetOverride) > Math.Abs(gravThrustRatio))
  394.                     SetGravityAcceleration(list, (float)targetOverride);
  395.                     //thisGravGen.SetValue("Gravity", (float)targetOverride);
  396.                 else if (targetOverride > 0 && gravThrustRatio >= 0 && Math.Abs(targetOverride) > Math.Abs(gravThrustRatio))
  397.                     SetGravityAcceleration(list, (float)targetOverride);
  398.                     //thisGravGen.SetValue("Gravity", (float)targetOverride);
  399.             }
  400.         }
  401.         else
  402.         {
  403.             SetGravityPower(list, false);
  404.             /*
  405.             bool isOn = thisGravGen.GetValue<bool>("OnOff");
  406.             if (isOn) //is on but should be off
  407.             {
  408.                 thisGravGen.ApplyAction("OnOff_Off");
  409.                 //thisGravGen.SetValue("Gravity", 0f);
  410.             }*/
  411.         }
  412.  
  413.     }
  414.  
  415.     //---Handle the rest of the off-grid gravity gens
  416.     foreach (IMyGravityGenerator thisGravGen in otherGens)
  417.     {
  418.         if (turnOn)
  419.         {
  420.             double gravThrustRatio = thisGravGen.WorldMatrix.Down.Dot(direction);
  421.             double gravDampingRatio;
  422.  
  423.             gravDampingRatio = thisGravGen.WorldMatrix.Up.Dot(velocityVec);
  424.  
  425.             thisGravGen.GravityAcceleration = (float)gravThrustRatio * 9.81f;
  426.             thisGravGen.Enabled = true;
  427.  
  428.             if (dampenersOn)
  429.             {
  430.                 double targetOverride = 0;
  431.  
  432.                 if (Math.Abs(gravDampingRatio) < 1)
  433.                     targetOverride = gravDampingRatio * gravityDriveDampenerScalingFactor;
  434.                 else
  435.                     targetOverride = Math.Sign(gravDampingRatio) * gravDampingRatio * gravDampingRatio * gravityDriveDampenerScalingFactor;
  436.  
  437.                 if (targetOverride < 0 && gravThrustRatio <= 0 && Math.Abs(targetOverride) > Math.Abs(gravThrustRatio))
  438.                     thisGravGen.GravityAcceleration = (float)targetOverride;
  439.                 else if (targetOverride > 0 && gravThrustRatio >= 0 && Math.Abs(targetOverride) > Math.Abs(gravThrustRatio))
  440.                     thisGravGen.GravityAcceleration = (float)targetOverride;
  441.             }
  442.         }
  443.         else
  444.         {
  445.             thisGravGen.Enabled = false;
  446.         }
  447.     }
  448. }
  449.  
  450. void SetGravityAcceleration(List<IMyGravityGenerator> list, float value)
  451. {
  452.     foreach (var block in list)
  453.         block.GravityAcceleration = value;
  454. }
  455.  
  456. void SetGravityPower(List<IMyGravityGenerator> list, bool value)
  457. {
  458.     foreach (var block in list)
  459.         block.Enabled = value;
  460. }
  461.  
  462. void ToggleMass(List<IMyVirtualMass> artMasses, bool toggleOn)
  463. {
  464.     foreach (IMyVirtualMass thisMass in artMasses)
  465.     {
  466.         bool isOn = thisMass.GetValue<bool>("OnOff");
  467.         if (isOn == toggleOn) //state is same
  468.         {
  469.             continue;
  470.         }
  471.         else if (toggleOn) //is off but should be on
  472.         {
  473.             thisMass.ApplyAction("OnOff_On");
  474.         }
  475.         else //is on but should be off
  476.         {
  477.             thisMass.ApplyAction("OnOff_Off");
  478.         }
  479.     }
  480. }
  481.  
  482. /*
  483. /// CHANGE LOG ///
  484. * Rewrote entire code to use direct user inputs - v5
  485. * Added OnOff argument handling - v6
  486. * Fixed dampeners not acting the same way in different directions - v7
  487. * Optimized gravity gen calcs - v8
  488. * Reduced block refreshing from 10 Hz to 0.1 Hz - v8
  489. * Added gyro locking when user is not applying inputs - v9
  490. * Added useGravityDriveAsInertialDampeners varialbe and arguments - v11
  491. * Added variable enableDampenersWhenNotControlled - v11
  492. * Added additional check for player input - v12
  493. */
Advertisement
Add Comment
Please, Sign In to add comment