jfullernz

Untitled

Apr 10th, 2019
1,713
1
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 59.15 KB | None | 1 0
  1.  
  2.         #region Introduction
  3.         /*
  4.         Introduction
  5.         ----------------
  6.         Hello and thank you for downloading Rdav's AI Mining Code
  7.         Rdav's AI Mining Code is an easy-setup Code that allows a player
  8.         to convert any vessel to a fully automated tunneling miner.
  9.        
  10.         Simply paste this code into a programmable block and in the terminal
  11.         the code will help you set this code up and give instructions.
  12.        
  13.         All the code is designed to be pretty easy to navigate
  14.         and the code will help you set it up automatically
  15.         any questions or queries don't hesitate to contact me!
  16.  
  17.        
  18.         Rdav 08/04/18
  19.         Jfullernz Battery update 10/04/19
  20.            
  21.         Suggestions Planned Features
  22.         -----------------------------
  23.         - Let me know what you think needs adding to code!
  24.  
  25.          ChangeLog:
  26.          * Release Version
  27.          * Updated: changed loc of line 56
  28.          * Updated serialization (new grid error)
  29.          * Updated isempty conditions //Update 002
  30.          * Updated mining with face
  31.          * updated not drop off in middle of row //Update 003
  32.          * Updated full limit system
  33.          * updated for RC exception fix
  34.          * Updated performance issues with large roids (capped ct) //Update 004
  35.  
  36.         */
  37.         #endregion
  38.  
  39.         //DO NOT TOUCH ANYTHING BELOW THIS LINE UNLESS INSTRUCTED =======================
  40.  
  41.         //Code Constructor For Initialisation
  42.         public Program()
  43.         { FirstTimeSetup(); }
  44.  
  45.         //Code Saves For Further Functions
  46.         public void Save()
  47.         { SaveCode();}
  48.  
  49.         //Primary Code Runtime
  50.         //========================
  51.  
  52.         //Setup Of Code Constants
  53.         #region SETUP
  54.  
  55.         //STORED VARIABLES
  56.         //----------------------------------------------------------------------------------------------------------------------
  57.  
  58.         //SUBCATEGORY PERMANENT ASSIGNMENTS:
  59.         string VERSION = "004"; //Script Version
  60.         double PrecisionMaxAngularVel = 0.6; //Maximum Precision Ship Angular Velocity
  61.         double RotationalSensitvity = 1; //Gain Applied To Gyros
  62.         bool ThrustCountOverride = true; //Togglable Override On Thrust Count
  63.         #endregion
  64.  
  65.         //Main Method Runtime
  66.         #region Main Method Autominer
  67.         void Main(string argument)
  68.         {
  69.             try
  70.             {
  71.  
  72.                 //Sets Up Code Runtime Indicators & Docking Route Checks
  73.                 //---------------------------------------------------------
  74.                 OP_BAR();
  75.                 Echo("General Information:\n----------------------------");
  76.  
  77.                 //System Error Readouts And Diag
  78.                 //---------------------------------
  79.                 #region Block Error Readouts
  80.  
  81.                 if (RC == null || RC.CubeGrid.GetCubeBlock(RC.Position) == null)
  82.                 { Echo("No Remote Control Found,\nInstall Forward Facing Remote Control Block And Press Recompile"); RC = null; return; }
  83.                 if (CONNECTOR == null || CONNECTOR.CubeGrid.GetCubeBlock(CONNECTOR.Position) == null)
  84.                 { Echo("No Connector Found,\nInstall Connector And Press Recompile "); CONNECTOR = null; return; }
  85.                 if (SENSOR == null || SENSOR.CubeGrid.GetCubeBlock(SENSOR.Position) == null)
  86.                 { Echo("No Sensor Found,\nInstall Sensor For Asteroid Detection And Press Recompile,\n(all sensor settings will automatically be set)"); SENSOR = null; return; }
  87.                 if (GYRO == null || GYRO.CubeGrid.GetCubeBlock(GYRO.Position) == null)
  88.                 { Echo("No Gyro Found,\nInstall Gyro And Press Recompile"); GYRO = null; return; }
  89.  
  90.                 if (CAF2_THRUST.Count > 15 && ThrustCountOverride)
  91.                 { Echo("Large Amount Of Thrusters Detected\nProgram Terminated To Prevent Performance Issues\n"+
  92.                     "Remove Unecessary Thrusters And Press Recompile (15 max)\n"+
  93.                     "This safety measure can be disabled on line 56"); return; }
  94.                 #endregion
  95.  
  96.                 //Dockpoint Handler
  97.                 //-----------------------
  98.                 Auto_DockpointDetect(); //Automatically Detects Docking Route
  99.                 var DOCKLIST = new List<Vector3D>();
  100.                 DOCKLIST.Add(DockPos3.Val);
  101.                 DOCKLIST.Add(DockPos2.Val);
  102.                 DOCKLIST.Add(DockPos1.Val);
  103.  
  104.                 if (DOCKLIST[0] == new Vector3D()) //Returns Error If No Docking Route
  105.                 { Echo("Cannot Find Docking Route\nPlease Dock To (Static) Connector\nTo Use As A Drop-Off Point"); return; }
  106.  
  107.                 //Manual Resetter Returns To Base
  108.                 //--------------------------------
  109.                 if (argument == "FIN")
  110.                 { MININGSTATUS.Val = "FIN"; HASFINISHED.Val = true; }
  111.                 if (argument == "RETURN")
  112.                 { MININGSTATUS.Val = "FULL"; HASFINISHED.Val = true; }
  113.  
  114.                 //Manual Override Enabler
  115.                 //-----------------------------
  116.                 bool ALL_RUN = true;
  117.                 foreach (var item in CONTROLLERS)
  118.                 { if ((item as IMyShipController).IsUnderControl) { ALL_RUN = false; } }
  119.                 if (ALL_RUN == false)
  120.                 {
  121.                     //Sets Standard Delogging Procedures
  122.                     RC.SetAutoPilotEnabled(false);
  123.                     for (int j = 0; j < CAF2_THRUST.Count; j++)
  124.                     { (CAF2_THRUST[j] as IMyThrust).ThrustOverride = 0; (CAF2_THRUST[j] as IMyThrust).Enabled = true; }
  125.                     GYRO.GyroOverride = false;
  126.                     CONNECTOR.Enabled = true;
  127.                     Echo("Manual Override Engaged\nStop controlling ship to continue program");
  128.  
  129.                     //Sets Docked Status If Docked
  130.                     if (CONNECTOR.Status == MyShipConnectorStatus.Connected)
  131.                     { COORD_ID.Val = 2; }
  132.                     return;
  133.                 }
  134.  
  135.                 //Updates Coordinates (not size) in a new Locator Scenario
  136.                 //-------------------------------------------------------------
  137.                 try
  138.                 {
  139.                     if (ISNOTBURIED.Val)
  140.                     {
  141.                         //Splits The Code Into Chunks
  142.                         string[] InputData = Me.CustomData.Split('@');
  143.                         string[] InputGpsList = InputData[1].Split(':');
  144.                         Vector3D TryVector = new Vector3D(double.Parse(InputGpsList[2]), double.Parse(InputGpsList[3]), double.Parse(InputGpsList[4]));
  145.  
  146.                         //Updates If Both Not Buried And Different
  147.                         if (TryVector != StoredAsteroidLoc.Val && ISNOTBURIED.Val)
  148.                         {
  149.                             StoredAsteroidLoc.Val = TryVector;
  150.                             MiningLogic(RC, DOCKLIST, GYRO, CONNECTOR, true);
  151.                             Echo("Updated Input Correctly");
  152.                             return;
  153.                         }
  154.                     }
  155.                 }
  156.                 catch { Echo("Incorrect Input Format,\n Refer Instructions, or Press 'Recompile' to reset."); }
  157.  
  158.                 if (StoredAsteroidLoc.Val == new Vector3D()) //Returns Error If No Docking Route
  159.                 { Echo("No Asteroid Input,\n Please Paste Valid GPS in Custom Data"); return; }
  160.  
  161.                 //Updates A Sensor If Ship Has One
  162.                 //---------------------------------------------
  163.                 if (SENSOR != null && SENSOR.DetectAsteroids == false)
  164.                 {
  165.                     SENSOR.DetectAsteroids = true;
  166.                     SENSOR.DetectPlayers = false;
  167.                     SENSOR.DetectOwner = false;
  168.                     SENSOR.DetectLargeShips = false;
  169.                     SENSOR.DetectSmallShips = false;
  170.                     SENSOR.LeftExtend = 50;
  171.                     SENSOR.RightExtend = 50;
  172.                     SENSOR.TopExtend = 50;
  173.                     SENSOR.FrontExtend = 50;
  174.                     SENSOR.BottomExtend = 50;
  175.                     SENSOR.BackExtend = 50;
  176.                 }
  177.  
  178.                 //Desets Thrust & Gyro
  179.                 //----------------------
  180.                 for (int j = 0; j < CAF2_THRUST.Count; j++)
  181.                 { (CAF2_THRUST[j] as IMyThrust).ThrustOverride = 0; } //(CAF2_THRUST[j] as IMyThrust).Enabled = true;
  182.  
  183.                 //Runs Primary Mnining Logic (only if not 0,0,0)
  184.                 //-------------------------------------------------
  185.                 Echo("CurrentRoid: " + Vector3D.Round(StoredAsteroidLoc.Val));
  186.                 Echo("CurrentCentre: "+Vector3D.Round(StoredAsteroidCentre.Val));
  187.                 Echo("CurrentRoidSize: "+Math.Round(StoredAsteroidDiameter.Val)+" Metres");
  188.  
  189.                 Echo("Is Vanilla RC A: " + Math.Round(StoredAsteroidDiameter.Val) + " Metres");
  190.                 Echo("Outside Asteroid? " + ISNOTBURIED.Val);
  191.                 Echo("Runtime: "+Math.Round(Runtime.LastRunTimeMs, 3) + " Ms");
  192.                 Echo("Version: " + VERSION + "\n");
  193.     var batteries = new List<IMyTerminalBlock>();
  194.     GridTerminalSystem.GetBlocksOfType<IMyBatteryBlock>(batteries);
  195.     IMyBatteryBlock thisBattery = batteries[0] as IMyBatteryBlock;
  196.                 BatteryLevel.Val = thisBattery.CurrentStoredPower*100;
  197.                 Echo("Battery Level: " + Math.Round(BatteryLevel.Val)+ "%\n");
  198.                
  199.                 MiningLogic(RC, DOCKLIST, GYRO, CONNECTOR,false);
  200.             }
  201.             catch (Exception e)
  202.             { Echo(e + ""); }
  203.         }
  204.         #endregion
  205.  
  206.         //Function Specific Functions
  207.         //============================
  208.  
  209.         //Used For Mining Management
  210.         #region Mining Logic #RFC#
  211.         /*=======================================================================================                            
  212.           Function: Mining Logic                  
  213.           ---------------------------------------                            
  214.           function will: The next generation of Rc manager, will automatically compensate for
  215.                          drifting to ensure the ship arrives on target quickly.
  216.         //----------==--------=------------=-----------=---------------=------------=-----=-----*/
  217.         Savable_Vector StoredAsteroidLoc = new Savable_Vector();
  218.         Savable_Vector StoredAsteroidCentre = new Savable_Vector();
  219.         Savable_Double StoredAsteroidDiameter = new Savable_Double();
  220.         Savable_Bool AbleToMine = new Savable_Bool();
  221.        
  222.        
  223.         void MiningLogic(IMyRemoteControl RC, List<Vector3D> DOCK_ROUTE,IMyGyro GYRO,IMyShipConnector CONNECTOR,bool RESET)
  224.         {
  225.             //Resets Function If A New Roid Is Detected
  226.             if (RESET)
  227.             {
  228.                 StoredAsteroidDiameter.Val = 0;
  229.                 StoredAsteroidCentre.Val = StoredAsteroidLoc.Val;
  230.                 ROW.Val = 1;
  231.                 COLUMN.Val = 1;
  232.                 MININGSTATUS.Val = "MINE";
  233.                 HASFINISHED.Val = false;
  234.                 return;
  235.             }
  236.             Echo("Mining Logic:\n--------------");
  237.  
  238.             //Sets If Full Or Not
  239.             bool IsEmpty = (SHIP_DRILLS[0].GetInventory().CurrentMass < 100); //sets primary is empty  
  240.             foreach (var CargoContainer in Cargo)
  241.             {
  242.                 IMyInventory CurrentCargo = CargoContainer.GetInventory(0);
  243.                 IsEmpty = CurrentCargo.CurrentMass > 900 ? false : IsEmpty;
  244.             }                            
  245.  
  246.             bool IsMassAboveThreshold = (double)SHIP_DRILLS[0].GetInventory().CurrentVolume > (double)SHIP_DRILLS[0].GetInventory().MaxVolume*0.80;
  247.  
  248.             if(IsMassAboveThreshold){Echo("Drill Inventory Is Currently Full");}
  249.             if(IsEmpty){Echo("Drill Inventory Is Currently Empty");}
  250.    
  251.             //bool IsEmpty = (CONNECTOR.GetInventory().CurrentMass < 100); //SHIP_DRILLS[0].GetInventory().MaxVolume - SHIP_DRILLS[0].GetInventory().CurrentVolume > 10 ||
  252.             //bool IsMassAboveThreshold = CONNECTOR.GetInventory().CurrentMass > 200000; //use connector for time being
  253.             if(IsEmpty && MININGSTATUS.Val != "FIN")
  254.             { MININGSTATUS.Val = "MINE";}
  255.             if (IsMassAboveThreshold && MININGSTATUS.Val != "FIN")
  256.             {  MININGSTATUS.Val = "FULL"; HASFINISHED.Val = true; }
  257.  
  258.             //Sets Drills:
  259.             if (SHIP_DRILLS[0].IsWorking == false && MININGSTATUS.Val == "MINE")
  260.             {
  261.                 for (int j = 0; j < SHIP_DRILLS.Count; j++)
  262.                 { (SHIP_DRILLS[j] as IMyShipDrill).Enabled = true; }
  263.             }
  264.             else if (SHIP_DRILLS[0].IsWorking == true && MININGSTATUS.Val != "MINE")
  265.             {
  266.                 for (int j = 0; j < SHIP_DRILLS.Count; j++)
  267.                 { (SHIP_DRILLS[j] as IMyShipDrill).Enabled = false; }
  268.             }
  269.  
  270.  
  271.             //If Full Go And Free Dock (stage 1)
  272.             if (MININGSTATUS.Val == "FULL" && ISNOTBURIED.Val)
  273.             {
  274.                 DockingIterator(true, DOCK_ROUTE, GYRO, CONNECTOR, RC);
  275.                 Echo("Status: Docking To Offload");
  276.                 return;
  277.             }
  278.  
  279.             //If Empty And Docked And Want To Go Mine, Undock (stage 2)
  280.              if (COORD_ID.Val != 0 && MININGSTATUS.Val == "MINE" && BatteryLevel.Val>80.00)
  281.             {
  282.                 DockingIterator(false, DOCK_ROUTE, GYRO, CONNECTOR, RC);
  283.                 Echo("Status: Undocking");
  284.                 return;
  285.             }
  286.  
  287.             //If Fin, then Stop operations (stage 4)
  288.             if (MININGSTATUS.Val == "FIN" && ISNOTBURIED.Val)
  289.             {
  290.                 DockingIterator(true, DOCK_ROUTE, GYRO, CONNECTOR, RC);
  291.                 Echo("Status: Finished Task, Returning To Drop Off");
  292.                 return;
  293.             }
  294.  
  295.             //Always Calls Mine Function If Undocked And Not Full
  296.             if (COORD_ID.Val == 0) //If Undocked
  297.             {
  298.  
  299.                 //Uses Sensor To Update Information On Asteroid Within 250m of Selected Asteroid (prevents Close Proximity Asteroid Failure)
  300.                 if (SENSOR.IsActive && (StoredAsteroidLoc.Val - RC.GetPosition()).Length() < 50 && StoredAsteroidCentre.Val == StoredAsteroidLoc.Val)
  301.                 {
  302.                     StoredAsteroidDiameter.Val = SENSOR.LastDetectedEntity.BoundingBox.Size.Length();
  303.                     StoredAsteroidCentre.Val = SENSOR.LastDetectedEntity.BoundingBox.Center;
  304.                 }
  305.  
  306.                 //If No Asteroid Detected Goes To Location To Detect Asteroid
  307.                 if (StoredAsteroidDiameter.Val == 0)
  308.                 {
  309.                     RC_Manager(StoredAsteroidLoc.Val, RC, false);
  310.                     return; //No Need For Remainder Of Logic
  311.                 }
  312.  
  313.                 //Toggles Should-be-Mining Based On Proximity
  314.                 double Dist_To_Mine_Start = (StoredAsteroidLoc.Val - RC.GetPosition()).Length();
  315.                 double Dist_To_Mine_Centre = (StoredAsteroidCentre.Val - RC.GetPosition()).Length();
  316.                 if (Dist_To_Mine_Start < 4) //Toggles Mining Mode On
  317.                 {AbleToMine.Val = true; }
  318.                 if (Dist_To_Mine_Centre > StoredAsteroidDiameter.Val + 40) //Toggles Mining Mode Off
  319.                 { AbleToMine.Val = false; }
  320.  
  321.                 //Goes To Location And Mines
  322.                 if (AbleToMine.Val == false)
  323.                 {
  324.                     RC_Manager(StoredAsteroidLoc.Val, RC, false);
  325.                     ISNOTBURIED.Val = true;
  326.                 }
  327.                 else if (AbleToMine.Val == true)
  328.                 {
  329.                     double DistToDrill = Math.Sqrt(SHIP_DRILLS.Count)*0.9; //Size of Ship
  330.                     if (Me.CubeGrid.ToString().Contains("Large")) //if large grid
  331.                     { DistToDrill = DistToDrill * 1.5; }
  332.                     if (StoredAsteroidDiameter.Val > DistToDrill) //Only if drill size is bigger than ship 9prevents array handlign issues
  333.                     { BoreMine(RC, StoredAsteroidLoc.Val, StoredAsteroidCentre.Val, StoredAsteroidDiameter.Val, DistToDrill, false); }
  334.                     else { Echo("No Asteroid Detected, Drill array too large"); }
  335.                 }
  336.  
  337.                 Echo("Status: Mining");
  338.                 //Echo(SHIP_DRILLS[0].GetInventory().MaxVolume + " Inventory Count"); // - SHIP_DRILLS[0].GetInventory().CurrentVolume +
  339.             }
  340.  
  341.         }
  342.         #endregion
  343.  
  344.         //Used For Generic BoreMining
  345.         #region BoreMine #RFC#
  346.         /*=======================================================================================                            
  347.           Function: RC_MANAGER                    
  348.           ---------------------------------------                            
  349.           function will: The next generation of Rc manager, will automatically compensate for
  350.                          drifting to ensure the ship arrives on target quickly.
  351.         //----------==--------=------------=-----------=---------------=------------=-----=-----*/
  352.         Savable_Int ROW = new Savable_Int();
  353.         Savable_Int COLUMN = new Savable_Int();
  354.         Savable_String MININGSTATUS = new Savable_String();
  355.         Savable_Bool ISNOTBURIED = new Savable_Bool();
  356.         Savable_Bool HASFINISHED = new Savable_Bool();
  357.         Savable_Double BatteryLevel = new Savable_Double();
  358.         List<IMyTerminalBlock> SHIP_DRILLS = new List<IMyTerminalBlock>();     //List Of all the ships drills
  359.         void BoreMine(IMyRemoteControl RC, Vector3D ROID_START, Vector3D ROID_CENTRE, double ROID_DIAMETER, double SHIPSIZE, bool Reset)
  360.         {
  361.  
  362.             //Setup Of Common Variables                        
  363.             Vector3D DronePosition = RC.GetPosition();
  364.             Vector3D Drone_To_Target = Vector3D.Normalize(ROID_CENTRE - DronePosition);
  365.  
  366.             //Generates XYZ Vectors
  367.             Vector3D X_ADD = Vector3D.Normalize(ROID_CENTRE - ROID_START);//Characteristic 'Forward' vector
  368.             Vector3D Y_ADD = Vector3D.CalculatePerpendicularVector(X_ADD); //Characteristic 'Left' vector
  369.             Vector3D Z_ADD = Vector3D.Cross(X_ADD, Y_ADD); //Characteristic 'Up' vector
  370.  
  371.             //Generates Array Of Starting Vectors
  372.             int Steps = MathHelper.Clamp((int)((ROID_DIAMETER * 0.3) / SHIPSIZE),1,16); //How many horizontal passes of the ship are required to eat the roid
  373.             double StepSize = SHIPSIZE;  //How big are those passes
  374.             Vector3D[,] GridCoords = new Vector3D[Steps+1, Steps+1]; //i as ROW.Val, j as COLUMN.Val
  375.             for (int i = 0; i < (Steps + 1); i++)
  376.             {
  377.                 for (int j = 0; j < (Steps + 1); j++)
  378.                 {
  379.                     Vector3D Ipos = (Math.Pow(-1, i) == -1) ? ROID_START + StepSize * (i - 1) * -1 * Z_ADD : ROID_START + StepSize * i * Z_ADD;
  380.                     Vector3D Jpos = (Math.Pow(-1, j) == -1) ? Ipos + StepSize * (j - 1) * -1 * Y_ADD : Ipos + StepSize * j * Y_ADD;
  381.                     GridCoords[i, j] = Jpos;
  382.                 }
  383.             }
  384.  
  385.             //Readouts
  386.             Echo("Has Finished Tunnel: " + HASFINISHED.Val); Echo(StepSize + " 'Step' Size");
  387.             Echo(ROW.Val + " /" + Steps + " Rows"); Echo(COLUMN.Val + " /" + Steps + " Columns"); //Echo((CurrentVectorEnd - DronePosition).Length() + " dist to iter++");
  388.  
  389.             //Generates Currently Targeted Vector As A Function Of 2 integers, ROW.Val and Depth
  390.             Vector3D CurrentVectorStart = GridCoords[ROW.Val,COLUMN.Val]; //Start Vector
  391.             Vector3D CurrentVectorEnd = CurrentVectorStart + X_ADD * (((ROID_CENTRE - ROID_START).Length() - ROID_DIAMETER/2) + ROID_DIAMETER*0.8); //Accounts for small input
  392.  
  393.             //Sets IsBuried And Has Finished
  394.             ISNOTBURIED.Val = (CurrentVectorStart - RC.GetPosition()).Length() < 4; //If Retracted Allows Switching Of Case
  395.             if ((CurrentVectorEnd - DronePosition).Length() < 1) { HASFINISHED.Val = true; } //If Reached End Toggle Finished
  396.  
  397.             //Inputs To Autopilot Function
  398.             double RollReqt = (float)(0.6 * (Vector3D.Dot(Z_ADD, RC.WorldMatrix.Down)));
  399.             GyroTurn6(X_ADD * 999999999999999999, RotationalSensitvity, GYRO, RC, RollReqt,PrecisionMaxAngularVel);
  400.  
  401.             if (HASFINISHED.Val) //Reverses Once Finished
  402.             { Vector_Thrust_Manager(CurrentVectorEnd, CurrentVectorStart, RC.GetPosition(), 2, 0.5, RC); }
  403.             else //else standard forward
  404.             {  Vector_Thrust_Manager(CurrentVectorStart, CurrentVectorEnd, RC.GetPosition(), 1, 0.5, RC);}
  405.            
  406.             //Iterates Based On Proximity
  407.             if ((CurrentVectorStart - DronePosition).Length() < 1 && ROW.Val == Steps && COLUMN.Val == Steps && HASFINISHED.Val)
  408.             {
  409.                 MININGSTATUS.Val = "FIN";
  410.                 return;
  411.             }
  412.             if ((CurrentVectorStart - DronePosition).Length() < 1 && ROW.Val == Steps && HASFINISHED.Val)
  413.             { COLUMN.Val++; ROW.Val = 1; HASFINISHED.Val = false; }
  414.             if ((CurrentVectorStart - DronePosition).Length() < 1 && HASFINISHED.Val)
  415.             { ROW.Val++; HASFINISHED.Val = false; }
  416.  
  417.         }
  418.         #endregion
  419.  
  420.  
  421.         //Used For Docking And Undocking Of Ships
  422.         #region Docking Iterator #RFC#
  423.         /*====================================================================================================================================                                  
  424.         Secondary Function: Dock Iterator                          
  425.         -----------------------------------------------------                                
  426.         Function will: Operate docking & undocking sequences for ships based on a Direct string Input                
  427.         //-=--------------=-----------=-----------=-------------------=-------------------=----------------------=----------------------------*/
  428.         Savable_Int COORD_ID = new Savable_Int(); //Current Docking ID
  429.         void DockingIterator(bool Docking,List<Vector3D> COORDINATES, IMyGyro GYRO,IMyShipConnector CONNECTOR, IMyRemoteControl RC)
  430.         {
  431.  
  432.             //Logic Check To Check Coords Are Within Limits
  433.             if (COORDINATES.Count < 3) { return; }
  434.  
  435.             //Changes Increment Based on Dock/Undock Requirement
  436.             int TargetID = 0;
  437.             int CurrentID = 0;
  438.             int iter_er = 0;
  439.             if (Docking == true)
  440.             { TargetID = 1; CurrentID = 0; iter_er = +1; }
  441.             if (Docking == false)
  442.             { TargetID = 0; CurrentID = 1; iter_er = -1; }
  443.  
  444.             //Toggles State Of Thrusters Connectors And Gyros On The Ship
  445.             if (Docking == true) { CONNECTOR.Connect();}
  446.             if (Docking == true && CONNECTOR.IsWorking == false) {CONNECTOR.Enabled = true; }
  447.             if (Docking == false && CONNECTOR.IsWorking == true) { CONNECTOR.Disconnect(); CONNECTOR.Enabled = true; }
  448.             if (CONNECTOR.Status == MyShipConnectorStatus.Connected && Docking == true)
  449.             {
  450.                 //for (int j = 0; j < CAF2_THRUST.Count; j++)
  451.                 //{(CAF2_THRUST[j] as IMyThrust).Enabled = false; }
  452.                 GYRO.GyroOverride = false;
  453.                 return;
  454.             }
  455.  
  456.             //Setting Up a Few Constants
  457.             Vector3D RollOrienter = Vector3D.Normalize(COORDINATES[COORDINATES.Count - 1] - COORDINATES[COORDINATES.Count - 2]);
  458.             Vector3D Connector_Direction = -1*ReturnConnectorDirection(CONNECTOR, RC);
  459.             double RollReqt = (float)(0.6 * (Vector3D.Dot(RollOrienter, Connector_Direction)));
  460.  
  461.             //Vertical Motion During Dock
  462.             if (COORD_ID.Val == COORDINATES.Count - 1)
  463.             {
  464.                 Vector3D DockingHeading = Vector3D.Normalize(COORDINATES[COORDINATES.Count - 3] - COORDINATES[COORDINATES.Count - 2]) * 9000000; //Heading
  465.                 GyroTurn6(DockingHeading, RotationalSensitvity, GYRO, RC, RollReqt,PrecisionMaxAngularVel); //Turn to heading
  466.                 if (Vector3D.Dot(RC.WorldMatrix.Forward, Vector3D.Normalize(DockingHeading)) > 0.98) //Error check for small rotational velocity
  467.                 { Vector_Thrust_Manager(COORDINATES[COORD_ID.Val - TargetID], COORDINATES[COORD_ID.Val - CurrentID], CONNECTOR.GetPosition(), 5, 0.7, RC); }  //Thrusts to point
  468.             }
  469.  
  470.             //Last/First External Coord During Dock
  471.             else if (COORD_ID.Val == 0)
  472.             { RC_Manager(COORDINATES[0], RC, false); }  //Standard Auto for first location
  473.  
  474.             //Horizontal And Iterative Statement
  475.             else
  476.             {
  477.                 var HEADING = Vector3D.Normalize(COORDINATES[COORD_ID.Val - CurrentID] - COORDINATES[COORD_ID.Val - TargetID]) * 9000000;
  478.                 Vector_Thrust_Manager(COORDINATES[COORD_ID.Val - TargetID], COORDINATES[COORD_ID.Val - CurrentID], CONNECTOR.GetPosition(), 8, 1, RC); //Runs docking sequence
  479.                 GyroTurn6(HEADING, RotationalSensitvity, GYRO, RC, RollReqt,PrecisionMaxAngularVel);
  480.             }
  481.  
  482.             //Logic checks and iterates
  483.             if (Docking == false && COORD_ID.Val == 0) { }
  484.             else if ((CONNECTOR.GetPosition() - COORDINATES[COORD_ID.Val - CurrentID]).Length() < 1 || ((RC.GetPosition() - COORDINATES[COORD_ID.Val - CurrentID]).Length() < 10 && COORD_ID.Val == 0))
  485.             {
  486.                 COORD_ID.Val = COORD_ID.Val + iter_er;
  487.                 if (COORD_ID.Val == COORDINATES.Count)
  488.                 { COORD_ID.Val = COORDINATES.Count - 1; }
  489.                 if (COORD_ID.Val < 0)
  490.                 { COORD_ID.Val = 0; }
  491.             }
  492.         }
  493.         //----------==--------=------------=-----------=---------------=------------=-------==--------=------------=-----------=----------
  494.  
  495.         #endregion
  496.  
  497.         //Standardised First Time Setup
  498.         #region First Time Setup #RFC#
  499.         /*====================================================================================================================                            
  500.         Function: FIRST_TIME_SETUP                  
  501.         ---------------------------------------                            
  502.         function will: Initiates Systems and initiasing Readouts to LCD
  503.         Performance Cost:
  504.        //======================================================================================================================*/
  505.         //SUBCATEGORY STORED BLOCKS
  506.         IMyRemoteControl RC;
  507.         IMyShipConnector CONNECTOR;
  508.         IMySensorBlock SENSOR;
  509.         List<IMyLargeTurretBase> DIRECTORS = new List<IMyLargeTurretBase>();
  510.         IMyRadioAntenna RADIO;
  511.         IMyGyro GYRO;
  512.         List<IMyTerminalBlock> CONTROLLERS = new List<IMyTerminalBlock>();
  513.         List<IMyTerminalBlock> Cargo = new List<IMyTerminalBlock>();
  514.         List<IMyTerminalBlock> DIRECTIONAL_FIRE = new List<IMyTerminalBlock>();  //Directional ship weaponry
  515.  
  516.         void FirstTimeSetup()
  517.         {
  518.             //Gathers Key Components
  519.             //-----------------------------------
  520.             //Sets Update Frequency
  521.             Runtime.UpdateFrequency = UpdateFrequency.Update10;
  522.  
  523.             //Gathers Remote Control
  524.             try
  525.             {
  526.                 List<IMyTerminalBlock> TEMP_RC = new List<IMyTerminalBlock>();
  527.                 GridTerminalSystem.GetBlocksOfType<IMyRemoteControl>(TEMP_RC, b => b.CubeGrid == Me.CubeGrid );
  528.                 RC = TEMP_RC[0] as IMyRemoteControl;
  529.             }
  530.             catch { }
  531.  
  532.             //GathersConnector  
  533.             try
  534.             {
  535.                 List<IMyTerminalBlock> TEMP_CON = new List<IMyTerminalBlock>();
  536.                 GridTerminalSystem.GetBlocksOfType<IMyShipConnector>(TEMP_CON, b => b.CubeGrid == Me.CubeGrid && b.CustomName.Contains("Ejector") == false);
  537.                 CONNECTOR = TEMP_CON[0] as IMyShipConnector;
  538.             }
  539.             catch { }
  540.  
  541.             //Sets Gyro
  542.             try
  543.             {
  544.                 List<IMyTerminalBlock> TEMP_GYRO = new List<IMyTerminalBlock>();
  545.                 GridTerminalSystem.GetBlocksOfType<IMyGyro>(TEMP_GYRO, b => b.CubeGrid == Me.CubeGrid);
  546.                 GYRO = TEMP_GYRO[0] as IMyGyro;
  547.             }
  548.             catch { }
  549.  
  550.             //Sets Sensor
  551.             try
  552.             {
  553.                 List<IMyTerminalBlock> TEMP_SENSOR= new List<IMyTerminalBlock>();
  554.                 GridTerminalSystem.GetBlocksOfType<IMySensorBlock>(TEMP_SENSOR, b => b.CubeGrid == Me.CubeGrid);
  555.                 SENSOR = TEMP_SENSOR[0] as IMySensorBlock;
  556.             }
  557.             catch { }
  558.  
  559.             //Initialising Dedicated Cargo
  560.             try
  561.             {
  562.                 GridTerminalSystem.GetBlocksOfType<IMyCargoContainer>(Cargo, b => b.CubeGrid == Me.CubeGrid);
  563.             }
  564.             catch
  565.             { }
  566.  
  567.             //Gathers Antennae
  568.             try
  569.             {
  570.                 List<IMyTerminalBlock> TEMP = new List<IMyTerminalBlock>();
  571.                 GridTerminalSystem.GetBlocksOfType<IMyRadioAntenna>(TEMP, b => b.CubeGrid == Me.CubeGrid);
  572.                 RADIO = TEMP[0] as IMyRadioAntenna;
  573.                 RADIO.SetValue<long>("PBList", Me.EntityId);
  574.                 RADIO.EnableBroadcasting = true;
  575.                 RADIO.Enabled = true;
  576.             }
  577.             catch { }
  578.  
  579.  
  580.  
  581.             //GathersControllers  
  582.             try
  583.             {
  584.                 GridTerminalSystem.GetBlocksOfType<IMyShipController>(CONTROLLERS, b => b.CubeGrid == Me.CubeGrid);
  585.             }
  586.             catch { }
  587.  
  588.             //Gathers Director Turret
  589.             try
  590.             {
  591.                 GridTerminalSystem.GetBlocksOfType<IMyLargeTurretBase>(DIRECTORS, b => b.CubeGrid == Me.CubeGrid);
  592.             }
  593.             catch { }
  594.  
  595.             //Gathers Drills
  596.             try
  597.             {
  598.                 GridTerminalSystem.GetBlocksOfType<IMyShipDrill>(SHIP_DRILLS, b => b.CubeGrid == Me.CubeGrid);
  599.             }
  600.             catch { }
  601.  
  602.             //Gathers Directional Weaponry
  603.             try
  604.             {
  605.                 GridTerminalSystem.GetBlocksOfType<IMyUserControllableGun>(DIRECTIONAL_FIRE,
  606.                     (block => block.GetType().Name == "MySmallMissileLauncher" || block.GetType().Name == "MySmallGatlingGun"
  607.                         || block.GetType().Name == "MySmallMissileLauncherReload")); //Collects the directional weaponry (in a group)
  608.             }
  609.             catch { }
  610.  
  611.             //Runs Thruster Setup
  612.             try
  613.             {
  614.                 CollectAndFire2(new Vector3D(), 0, 0, RC.GetPosition(), RC);
  615.                 for (int j = 0; j < CAF2_THRUST.Count; j++)
  616.                 { CAF2_THRUST[j].SetValue<float>("Override", 0.0f); CAF2_THRUST[j].ApplyAction("OnOff_On"); }
  617.             }
  618.             catch { }
  619.  
  620.             //Loads Saved Data
  621.             try
  622.             {
  623.                 //Retrieves And Deserializes Saved Data
  624.                 //string DataInput = Me.CustomData;
  625.                 DeSerializer(Storage);
  626.             }
  627.             catch
  628.             { }
  629.  
  630.             //Creates User Interface
  631.             try
  632.             {
  633.                 Me.CustomData = "Paste Asteroid GPS Here: \n===========================\n@" + "GPS:Mine:" + StoredAsteroidLoc.Val.X + ":" + StoredAsteroidLoc.Val.Y + ":" + StoredAsteroidLoc.Val.Z +
  634.                     "@\n\nInstructions:\n===========================\nPaste GPS coords of point NEAR asteroid\nbetween the symbols." +
  635.                     "\nDo NOT include the 'at' symbol in the GPS name\nErrors Will be displayed in the terminal\n\n"+
  636.                     "Hints/Tips:\n===========================\n"+
  637.                     "-Look in the terminal for live mining progress\n"+
  638.                     "-Paste GPS near the ore you want collected for faster mining\n" +
  639.                     "-NEVER paste a GPS from inside an asteroid \n" +
  640.                     "-Rename any connectors you don't want the code\n to use as docking points as 'Ejector' \n" +
  641.                     "-The code uses the GPS as a starting point so for\n larger ships keep this GPS further away from the asteroid\n" +
  642.                     "-The miner will remember the orientation you dock with \n so remember to dock in the direction you want to launch\n" +
  643.                     "-You can reassign docking coordinates at any point\n by manually overriding and docking somewhere else \n" +
  644.                     "-To cancel a task and return miner to base \n run the PB with the argument 'FIN'";
  645.             }
  646.             catch
  647.             { }
  648.  
  649.         }
  650.  
  651.         void SaveCode()
  652.         {
  653.             //Serializes Savable Data
  654.             //Me.CustomData = Serializer();
  655.             Storage = Serializer();
  656.         }
  657.         #endregion
  658.  
  659.         //Used For Automatic Dockpoint Recognition
  660.         #region Auto-DockpointDetect #RFC#
  661.         /*=======================================================================================                            
  662.           Function: Auto-DockpointDetect                  
  663.           ---------------------------------------                            
  664.           function will: Automatically detect dockpoints for usage
  665.         //----------==--------=------------=-----------=---------------=------------=-----=-----*/
  666.         Savable_Vector DockPos1 = new Savable_Vector(); //Conncetor Location
  667.         Savable_Vector DockPos2 = new Savable_Vector(); //Straight Up Location
  668.         Savable_Vector DockPos3 = new Savable_Vector(); //Straight Up And Forward Location
  669.         IMyShipConnector OtherTempConnector;
  670.  
  671.         void Auto_DockpointDetect()
  672.         {
  673.             //if Docked Only And A new Dockpoint Assign New Dockpoint
  674.             if (CONNECTOR.Status == MyShipConnectorStatus.Connected)
  675.             {
  676.                 OtherTempConnector = CONNECTOR.OtherConnector;
  677.                 DockPos1.Val = OtherTempConnector.GetPosition() + OtherTempConnector.WorldMatrix.Forward * (0.75);
  678.                 DockPos2.Val = OtherTempConnector.GetPosition() + OtherTempConnector.WorldMatrix.Forward * (6);
  679.                 DockPos3.Val = DockPos2.Val + RC.WorldMatrix.Forward * 40;
  680.                 COORD_ID.Val = 2;
  681.             }
  682.  
  683.             //If Other Connector Is not Null Reassign Docking Coordinates
  684.             if (OtherTempConnector != null)
  685.             {
  686.  
  687.             }
  688.  
  689.         }
  690.         #endregion
  691.  
  692.         //Primary Generic Functions
  693.         //==========================
  694.  
  695.         //Use For General Drone Flying:
  696.         #region RC_Manager #RFC#
  697.         /*=======================================================================================                            
  698.           Function: RC_MANAGER                    
  699.           ---------------------------------------                            
  700.           function will: The next generation of Rc manager, will automatically compensate for
  701.                          drifting to ensure the ship arrives on target quickly.
  702.         //----------==--------=------------=-----------=---------------=------------=-----=-----*/
  703.         void RC_Manager(Vector3D TARGET, IMyRemoteControl RC, bool TURN_ONLY )
  704.         {
  705.             //Uses Rotation Control To Handle Max Rotational Velocity
  706.             //---------------------------------------------------------
  707.             if (RC.GetShipVelocities().AngularVelocity.AbsMax() > PrecisionMaxAngularVel)
  708.             { Echo("Slowing Rotational Velocity");  RC.SetAutoPilotEnabled(false); return; }
  709.  
  710.             //Setup Of Common Variables                        
  711.             //--------------------------------------------
  712.             Vector3D DronePosition = RC.GetPosition();
  713.             Vector3D Drone_To_Target = Vector3D.Normalize(TARGET - DronePosition);
  714.  
  715.             //Override Direction Detection
  716.             //-------------------------------
  717.             double To_Target_Angle = Vector3D.Dot(Vector3D.Normalize(RC.GetShipVelocities().LinearVelocity), Drone_To_Target);
  718.             double Ship_Velocity = RC.GetShipVelocities().LinearVelocity.Length();
  719.  
  720.             //Turn Only: (Will drift ship automatically)
  721.             //--------------------------------------------
  722.             if (TURN_ONLY)
  723.             {
  724.                 RC.ClearWaypoints();
  725.                 RC.AddWaypoint(TARGET, "1");
  726.                 RC.AddWaypoint(TARGET, "cc1");
  727.                 RC.ApplyAction("AutoPilot_On");
  728.                 RC.ApplyAction("CollisionAvoidance_Off");
  729.                 RC.ControlThrusters = false;
  730.                 return;
  731.             }
  732.  
  733.             //Drift Cancellation Enabled:
  734.             //-----------------------------
  735.             if (To_Target_Angle < 0.4 && Ship_Velocity > 3)
  736.             {
  737.                 Echo("Drift Cancellation Enabled");
  738.  
  739.                 //Aim Gyro To Reflected Vector
  740.                 Vector3D DRIFT_VECTOR = Vector3D.Normalize(RC.GetShipVelocities().LinearVelocity);
  741.                 Vector3D REFLECTED_DRIFT_VECTOR = -1*(Vector3D.Normalize(Vector3D.Reflect(DRIFT_VECTOR, Drone_To_Target)));
  742.                 Vector3D AIMPINGPOS = (-1 * DRIFT_VECTOR * 500) + DronePosition;
  743.  
  744.                 //Sets Autopilot To Turn
  745.                 RC.ClearWaypoints();
  746.                 RC.AddWaypoint(AIMPINGPOS, "1");
  747.                 RC.AddWaypoint(AIMPINGPOS, "cc1");
  748.                 RC.ApplyAction("AutoPilot_On");
  749.                 RC.ApplyAction("CollisionAvoidance_Off");
  750.  
  751.             }
  752.  
  753.             //System Standard Operation:
  754.             //---------------------------
  755.             else
  756.             {
  757.                 Echo("Drift Cancellation Disabled");
  758.  
  759.                 //Assign To RC, Clear And Refresh Command                        
  760.                 RC.ClearWaypoints();
  761.                 RC.ControlThrusters = true;
  762.                 RC.AddWaypoint(TARGET, "1");
  763.                 RC.AddWaypoint(TARGET, "cc1");
  764.                 RC.ApplyAction("AutoPilot_On");                   //RC toggle
  765.                 RC.ApplyAction("DockingMode_Off");                //Precision Mode
  766.                 RC.ApplyAction("CollisionAvoidance_On");          //Col avoidance
  767.            
  768.             }
  769.  
  770.         }
  771.         #endregion
  772.  
  773.         //Use For Precise Turning (docking, mining, attacking)
  774.         #region GyroTurn6 #RFC#
  775.         /*=======================================================================================                            
  776.           Function: GyroTurn6                    
  777.           ---------------------------------------                            
  778.           function will: The next generation of Gyroturn, designed to be performance optimised
  779.                          over actuating performance, it detects orientation and directly applies overrides
  780.         //----------==--------=------------=-----------=---------------=------------=-----=-----*/
  781.         void GyroTurn6(Vector3D TARGET, double GAIN, IMyGyro GYRO, IMyRemoteControl REF_RC, double ROLLANGLE,double MAXANGULARVELOCITY)
  782.         {
  783.             //Ensures Autopilot Not Functional
  784.             REF_RC.SetAutoPilotEnabled(false);
  785.             Echo("Running Gyro Control Program");
  786.  
  787.             //Detect Forward, Up & Pos
  788.             Vector3D ShipForward = REF_RC.WorldMatrix.Forward;
  789.             Vector3D ShipUp = REF_RC.WorldMatrix.Up;
  790.             Vector3D ShipPos = REF_RC.GetPosition();
  791.  
  792.             //Create And Use Inverse Quatinion                  
  793.             Quaternion Quat_Two = Quaternion.CreateFromForwardUp(ShipForward, ShipUp);
  794.             var InvQuat = Quaternion.Inverse(Quat_Two);
  795.             Vector3D DirectionVector = Vector3D.Normalize(TARGET - ShipPos); //RealWorld Target Vector
  796.             Vector3D RCReferenceFrameVector = Vector3D.Transform(DirectionVector, InvQuat); //Target Vector In Terms Of RC Block
  797.  
  798.             //Convert To Local Azimuth And Elevation
  799.             double ShipForwardAzimuth = 0; double ShipForwardElevation = 0;
  800.             Vector3D.GetAzimuthAndElevation(RCReferenceFrameVector, out  ShipForwardAzimuth, out ShipForwardElevation);
  801.  
  802.             //Does Some Rotations To Provide For any Gyro-Orientation
  803.             var RC_Matrix = REF_RC.WorldMatrix.GetOrientation();
  804.             var Vector = Vector3.Transform((new Vector3D(ShipForwardElevation, ShipForwardAzimuth, ROLLANGLE)), RC_Matrix); //Converts To World
  805.             var TRANS_VECT = Vector3.Transform(Vector, Matrix.Transpose(GYRO.WorldMatrix.GetOrientation()));  //Converts To Gyro Local
  806.  
  807.             //Applies To Scenario
  808.             GYRO.Pitch = (float)MathHelper.Clamp((-TRANS_VECT.X * GAIN), -MAXANGULARVELOCITY, MAXANGULARVELOCITY);
  809.             GYRO.Yaw = (float)MathHelper.Clamp(((-TRANS_VECT.Y) * GAIN), -MAXANGULARVELOCITY, MAXANGULARVELOCITY);
  810.             GYRO.Roll = (float)MathHelper.Clamp(((-TRANS_VECT.Z) * GAIN), -MAXANGULARVELOCITY, MAXANGULARVELOCITY);
  811.             GYRO.GyroOverride = true;
  812.  
  813.             //GYRO.SetValueFloat("Pitch", (float)((TRANS_VECT.X) * GAIN));    
  814.             //GYRO.SetValueFloat("Yaw", (float)((-TRANS_VECT.Y) * GAIN));
  815.             //GYRO.SetValueFloat("Roll", (float)((-TRANS_VECT.Z) * GAIN));
  816.         }
  817.         #endregion
  818.        
  819.         //Use For Precise Thrusting (docking, mining, attacking)
  820.         #region CollectAndFire2 #RFC#
  821.         /*=======================================================================================                            
  822.           Function: COLLECT_AND_FIRE                      
  823.           ---------------------------------------                            
  824.           function will: Collect thrust pointing in a input direction and fire said thrust
  825.                          towards that point, remember to deset
  826.         //----------==--------=------------=-----------=---------------=------------=-----=-----*/
  827.         class Thrust_info                   //Basic Information For Axial Thrust
  828.         {
  829.             public double PositiveMaxForce;
  830.             public double NegativeMaxForce;
  831.             public List<IMyThrust> PositiveThrusters;
  832.             public List<IMyThrust> NegativeThrusters;
  833.             public double VCF;
  834.             public Thrust_info(Vector3D DIRECT, IMyGridTerminalSystem GTS, IMyCubeGrid MEGRID)
  835.             {
  836.                 PositiveThrusters = new List<IMyThrust>(); NegativeThrusters = new List<IMyThrust>();
  837.                 List<IMyTerminalBlock> TEMP_RC = new List<IMyTerminalBlock>();
  838.                 GTS.GetBlocksOfType<IMyThrust>(PositiveThrusters, block => Vector3D.Dot(-1 * block.WorldMatrix.Forward, DIRECT) > 0.7 && block.CubeGrid == MEGRID);
  839.                 GTS.GetBlocksOfType<IMyThrust>(NegativeThrusters, block => Vector3D.Dot(block.WorldMatrix.Forward, DIRECT) > 0.7 && block.CubeGrid == MEGRID);
  840.                 double POWER_COUNT = 0;
  841.                 foreach (var item in PositiveThrusters)
  842.                 { POWER_COUNT = POWER_COUNT + item.MaxEffectiveThrust; }
  843.                 PositiveMaxForce = POWER_COUNT;
  844.                 POWER_COUNT = 0;
  845.                 foreach (var item in NegativeThrusters)
  846.                 { POWER_COUNT = POWER_COUNT + item.MaxEffectiveThrust; }
  847.                 NegativeMaxForce = POWER_COUNT;
  848.             }
  849.         }
  850.         Thrust_info CAF2_FORWARD;
  851.         Thrust_info CAF2_UP;
  852.         Thrust_info CAF2_RIGHT;
  853.         List<Thrust_info> CAFTHI = new List<Thrust_info>();
  854.  
  855.         List<IMyTerminalBlock> CAF2_THRUST = new List<IMyTerminalBlock>();
  856.         bool C_A_F_HASRUN = false;
  857.         double CAF2_BRAKING_COUNT = 99999999;
  858.  
  859.         double CAF_SHIP_DECELLERATION;                        //Outputs current decelleration
  860.         double CAF_STOPPING_DIST;                             //Outputs current stopping distance
  861.         double CAF_DIST_TO_TARGET;                            //Outputs distance to target
  862.  
  863.         void CollectAndFire2(Vector3D INPUT_POINT, double INPUT_VELOCITY, double INPUT_MAX_VELOCITY, Vector3D REFPOS, IMyRemoteControl RC)
  864.         {
  865.             //Function Initialisation
  866.             //--------------------------------------------------------------------
  867.             if (C_A_F_HASRUN == false)
  868.             {
  869.                 //Initialise Classes And Basic System
  870.                 CAF2_FORWARD = new Thrust_info(RC.WorldMatrix.Forward, GridTerminalSystem, Me.CubeGrid);
  871.                 CAF2_UP = new Thrust_info(RC.WorldMatrix.Up, GridTerminalSystem, Me.CubeGrid);
  872.                 CAF2_RIGHT = new Thrust_info(RC.WorldMatrix.Right, GridTerminalSystem, Me.CubeGrid);
  873.                 CAFTHI = new List<Thrust_info>() { CAF2_FORWARD, CAF2_UP, CAF2_RIGHT };
  874.                 GridTerminalSystem.GetBlocksOfType<IMyThrust>(CAF2_THRUST, block => block.CubeGrid == Me.CubeGrid);
  875.                 C_A_F_HASRUN = true;
  876.  
  877.                 //Initialises Braking Component
  878.                 foreach (var item in CAFTHI)
  879.                 {
  880.                     CAF2_BRAKING_COUNT = (item.PositiveMaxForce < CAF2_BRAKING_COUNT) ? item.PositiveMaxForce : CAF2_BRAKING_COUNT;
  881.                     CAF2_BRAKING_COUNT = (item.NegativeMaxForce < CAF2_BRAKING_COUNT) ? item.PositiveMaxForce : CAF2_BRAKING_COUNT;
  882.                 }
  883.             }
  884.             Echo("Running Thruster Control Program");
  885.  
  886.             //Generating Maths To Point and decelleration information etc.
  887.             //--------------------------------------------------------------------
  888.             double SHIPMASS = Convert.ToDouble(RC.CalculateShipMass().PhysicalMass);
  889.             Vector3D INPUT_VECTOR = Vector3D.Normalize(INPUT_POINT - REFPOS);
  890.             double VELOCITY = RC.GetShipSpeed();
  891.             CAF_DIST_TO_TARGET = (REFPOS - INPUT_POINT).Length();
  892.             CAF_SHIP_DECELLERATION = 0.75 * (CAF2_BRAKING_COUNT / SHIPMASS);
  893.             CAF_STOPPING_DIST = (((VELOCITY * VELOCITY) - (INPUT_VELOCITY * INPUT_VELOCITY))) / (2 * CAF_SHIP_DECELLERATION);
  894.  
  895.             //If Within Stopping Distance Halts Programme
  896.             //--------------------------------------------
  897.             if (!(CAF_DIST_TO_TARGET > (CAF_STOPPING_DIST + 0.25)) || CAF_DIST_TO_TARGET < 0.25 || VELOCITY > INPUT_MAX_VELOCITY)
  898.             { foreach (var thruster in CAF2_THRUST) { (thruster as IMyThrust).ThrustOverride = 0; } return; }
  899.             //dev notes, this is the most major source of discontinuity between theorised system response
  900.  
  901.             //Reflects Vector To Cancel Orbiting
  902.             //------------------------------------
  903.             Vector3D DRIFT_VECTOR = Vector3D.Normalize(RC.GetShipVelocities().LinearVelocity + RC.WorldMatrix.Forward * 0.00001);
  904.             Vector3D R_DRIFT_VECTOR = -1 * Vector3D.Normalize(Vector3D.Reflect(DRIFT_VECTOR, INPUT_VECTOR));
  905.             R_DRIFT_VECTOR = ((Vector3D.Dot(R_DRIFT_VECTOR, INPUT_VECTOR) < -0.3)) ? 0 * R_DRIFT_VECTOR : R_DRIFT_VECTOR;
  906.             INPUT_VECTOR = Vector3D.Normalize((4 * R_DRIFT_VECTOR) + INPUT_VECTOR);
  907.  
  908.             //Components Of Input Vector In FUR Axis
  909.             //----------------------------------------
  910.             double F_COMP_IN = Vector_Projection(INPUT_VECTOR, RC.WorldMatrix.Forward);
  911.             double U_COMP_IN = Vector_Projection(INPUT_VECTOR, RC.WorldMatrix.Up);
  912.             double R_COMP_IN = Vector_Projection(INPUT_VECTOR, RC.WorldMatrix.Right);
  913.  
  914.             //Calculate MAX Allowable in Each Axis & Length
  915.             //-----------------------------------------------
  916.             double F_COMP_MAX = (F_COMP_IN > 0) ? CAF2_FORWARD.PositiveMaxForce : -1 * CAF2_FORWARD.NegativeMaxForce;
  917.             double U_COMP_MAX = (U_COMP_IN > 0) ? CAF2_UP.PositiveMaxForce : -1 * CAF2_UP.NegativeMaxForce;
  918.             double R_COMP_MAX = (R_COMP_IN > 0) ? CAF2_RIGHT.PositiveMaxForce : -1 * CAF2_RIGHT.NegativeMaxForce;
  919.             double MAX_FORCE = Math.Sqrt(F_COMP_MAX * F_COMP_MAX + U_COMP_MAX * U_COMP_MAX + R_COMP_MAX * R_COMP_MAX);
  920.  
  921.             //Apply Length to Input Components and Calculates Smallest Multiplier
  922.             //--------------------------------------------------------------------
  923.             double F_COMP_PROJ = F_COMP_IN * MAX_FORCE;
  924.             double U_COMP_PROJ = U_COMP_IN * MAX_FORCE;
  925.             double R_COMP_PROJ = R_COMP_IN * MAX_FORCE;
  926.             double MULTIPLIER = 1;
  927.             MULTIPLIER = (F_COMP_MAX / F_COMP_PROJ < MULTIPLIER) ? F_COMP_MAX / F_COMP_PROJ : MULTIPLIER;
  928.             MULTIPLIER = (U_COMP_MAX / U_COMP_PROJ < MULTIPLIER) ? U_COMP_MAX / U_COMP_PROJ : MULTIPLIER;
  929.             MULTIPLIER = (R_COMP_MAX / R_COMP_PROJ < MULTIPLIER) ? R_COMP_MAX / R_COMP_PROJ : MULTIPLIER;
  930.  
  931.             //Calculate Multiplied Components
  932.             //---------------------------------
  933.             CAF2_FORWARD.VCF = ((F_COMP_PROJ * MULTIPLIER) / F_COMP_MAX) * Math.Sign(F_COMP_MAX);
  934.             CAF2_UP.VCF = ((U_COMP_PROJ * MULTIPLIER) / U_COMP_MAX) * Math.Sign(U_COMP_MAX);
  935.             CAF2_RIGHT.VCF = ((R_COMP_PROJ * MULTIPLIER) / R_COMP_MAX) * Math.Sign(R_COMP_MAX);
  936.  
  937.             //Runs System Thrust Application
  938.             //----------------------------------
  939.             Dictionary<IMyThrust, float> THRUSTVALUES = new Dictionary<IMyThrust, float>();
  940.             foreach (var thruster in CAF2_THRUST) { THRUSTVALUES.Add((thruster as IMyThrust), 0f); }
  941.  
  942.             foreach (var THRUSTSYSTM in CAFTHI)
  943.             {
  944.                 List<IMyThrust> POSTHRUST = THRUSTSYSTM.PositiveThrusters;
  945.                 List<IMyThrust> NEGTHRUST = THRUSTSYSTM.NegativeThrusters;
  946.                 if (THRUSTSYSTM.VCF < 0) { POSTHRUST = THRUSTSYSTM.NegativeThrusters; NEGTHRUST = THRUSTSYSTM.PositiveThrusters; }
  947.                 foreach (var thruster in POSTHRUST) { THRUSTVALUES[thruster as IMyThrust] = (float)(Math.Abs(THRUSTSYSTM.VCF))*(thruster as IMyThrust).MaxThrust; }
  948.                 foreach (var thruster in NEGTHRUST) { THRUSTVALUES[thruster as IMyThrust] = 1; }//(float)0.01001;}
  949.                 foreach (var thruster in THRUSTVALUES) { thruster.Key.ThrustOverride = thruster.Value; } //thruster.Key.ThrustOverride = thruster.Value;
  950.             }
  951.         }
  952.         //----------==--------=------------=-----------=---------------=------------=-------==--------=-----
  953.         #endregion
  954.  
  955.         //Used For Precise Thrusting Along A Vector (docking, mining, attacking)
  956.         #region Vector Thrust Manager #RFC#
  957.         /*====================================================================================================================================                                  
  958.         Secondary Function: PRECISION MANAGER                            
  959.         -----------------------------------------------------                                
  960.         Function will: Given two inputs manage vector-based thrusting              
  961.         Inputs: DIRECTION, BLOCK                
  962.         //-=--------------=-----------=-----------=-------------------=-------------------=----------------------=----------------------------*/
  963.         void Vector_Thrust_Manager(Vector3D PM_START, Vector3D PM_TARGET, Vector3D PM_REF, double PR_MAX_VELOCITY, double PREC, IMyRemoteControl RC)
  964.         {
  965.             Vector3D VECTOR = Vector3D.Normalize(PM_START - PM_TARGET);
  966.             Vector3D GOTOPOINT = PM_TARGET + VECTOR * MathHelper.Clamp((((PM_REF - PM_TARGET).Length() - 0.2)), 0, (PM_START - PM_TARGET).Length());
  967.             double DIST_TO_POINT = MathHelper.Clamp((GOTOPOINT - PM_REF).Length(), 0, (PM_START - PM_TARGET).Length());
  968.  
  969.             if (DIST_TO_POINT > PREC)
  970.             { CollectAndFire2(GOTOPOINT, 0, PR_MAX_VELOCITY*2, PM_REF, RC); }
  971.             else
  972.             { CollectAndFire2(PM_TARGET, 0, PR_MAX_VELOCITY, PM_REF, RC); }
  973.         }
  974.         //----------==--------=------------=-----------=---------------=------------=-------==--------=------------=-----------=----------
  975.         #endregion
  976.  
  977.         //Use For Magnitudes Of Vectors In Directions
  978.         #region Vector Projection #RFC#
  979.         /*=================================================                          
  980.           Function: Vector Projection Useful For Generic
  981.                     quantity in direction algorithms          
  982.           ---------------------------------------     */
  983.         double Vector_Projection(Vector3D IN, Vector3D Axis)
  984.         {
  985.             double OUT = 0;
  986.             OUT = Vector3D.Dot(IN, Axis) / IN.Length();
  987.             if (OUT + "" == "NaN")
  988.             { OUT = 0; }
  989.             return OUT;
  990.         }
  991.         #endregion
  992.  
  993.         //Use For General Display
  994.         #region RFC Function bar #RFC#
  995.         /*=================================================                          
  996.           Function: RFC Function bar #RFC#                  
  997.           ---------------------------------------     */
  998.         string[] FUNCTION_BAR = new string[] { "", " ===||===", " ==|==|==", " =|====|=", " |======|", "  ======" };
  999.         int FUNCTION_TIMER = 0;                                     //For Runtime Indicator
  1000.         void OP_BAR()
  1001.         {
  1002.             FUNCTION_TIMER++;
  1003.             Echo("     ~ MKII RFC AI Running~  \n               " + FUNCTION_BAR[FUNCTION_TIMER] + "");
  1004.             if (FUNCTION_TIMER == 5) { FUNCTION_TIMER = 0; }
  1005.         }
  1006.         #endregion
  1007.  
  1008.         //Returns Connector Orientation As A String
  1009.         #region Connector Direction #RFC#
  1010.         /*=======================================================================================                            
  1011.           Function: Connector Direction                    
  1012.           ---------------------------------------                            
  1013.           function will: return a string for the RC to use for docking procedures                                                      
  1014.         //=======================================================================================*/
  1015.         Vector3D ReturnConnectorDirection(IMyShipConnector CONNECTOR, IMyRemoteControl RC)
  1016.         {
  1017.             if (CONNECTOR.Orientation.Forward == RC.Orientation.TransformDirection(Base6Directions.Direction.Down))
  1018.             { return RC.WorldMatrix.Left; }  //Connector is the bottom of ship
  1019.             if (CONNECTOR.Orientation.Forward == RC.Orientation.TransformDirection(Base6Directions.Direction.Up))
  1020.             { return RC.WorldMatrix.Right; }  //Connector is on the top of the ship
  1021.             if (CONNECTOR.Orientation.Forward == RC.Orientation.TransformDirection(Base6Directions.Direction.Right))
  1022.             { return RC.WorldMatrix.Up; }  //Connector is on the left of the ship
  1023.             if (CONNECTOR.Orientation.Forward == RC.Orientation.TransformDirection(Base6Directions.Direction.Left))
  1024.             { return RC.WorldMatrix.Down; }  //Connector is on the right of the ship
  1025.             return RC.WorldMatrix.Down;
  1026.         }
  1027.         #endregion
  1028.  
  1029.         //Generic Constructors Used For Serialization & Saving/Loading
  1030.         #region StandardSerializer #RFC#
  1031.         /*=======================================================================================                            
  1032.           Function: Serializer                  
  1033.           ---------------------------------------                            
  1034.           function will: Serialize & Deserialize any variable using the Savable_ tag
  1035.         //----------==--------=------------=-----------=---------------=------------=-----=-----*/
  1036.  
  1037.         //Serialization Lists (All static, bahhh)
  1038.         static List<Savable_String> SavableStrings = new List<Savable_String>();
  1039.         static List<Savable_Int> SavableInts = new List<Savable_Int>();
  1040.         static List<Savable_Vector> SavableVectors = new List<Savable_Vector>();
  1041.         static List<Savable_Double> SavableDoubles = new List<Savable_Double>();
  1042.         static List<Savable_Bool> SavableBools = new List<Savable_Bool>();
  1043.  
  1044.         //Serializable Variable Types
  1045.         class Savable_String //Savable String Interface
  1046.         { public string Val = ""; public Savable_String() { SavableStrings.Add(this); } }
  1047.         class Savable_Int //Savable Int Interface
  1048.         { public int Val = 0; public Savable_Int() { SavableInts.Add(this); } }
  1049.         class Savable_Vector //Savable Vector3D Interface
  1050.         { public Vector3D Val = new Vector3D(0, 0, 0); public Savable_Vector() { SavableVectors.Add(this); } }
  1051.         class Savable_Double //Savable Double Interface
  1052.         { public double Val = 0; public Savable_Double() { SavableDoubles.Add(this); } }
  1053.         class Savable_Bool//Savable Boolean Interface
  1054.         { public bool Val = true; public Savable_Bool() { SavableBools.Add(this); } }
  1055.  
  1056.         //Methods For Serialization/Deserialization
  1057.         string Serializer()
  1058.         {
  1059.  
  1060.             //Saves GridId First (Prevents Reoccuring ID feature)
  1061.             string SaveString = Me.CubeGrid.EntityId + "";
  1062.  
  1063.             //Iterates Through Strings
  1064.             SaveString = SaveString + "/";
  1065.             foreach (var item in SavableStrings)
  1066.             {
  1067.                 SaveString = SaveString + item.Val + "^";
  1068.             }
  1069.  
  1070.             //Iterates Through Ints
  1071.             SaveString = SaveString + "/";
  1072.             foreach (var item in SavableInts)
  1073.             {
  1074.                 SaveString = SaveString + item.Val + "^";
  1075.             }
  1076.  
  1077.             //Iterates Through 3DVectors
  1078.             SaveString = SaveString + "/";
  1079.             foreach (var item in SavableVectors)
  1080.             {
  1081.                 SaveString = SaveString + Vector3D.Round(item.Val, 2) + "^";
  1082.             }
  1083.  
  1084.             //Iterates Through Doubles
  1085.             SaveString = SaveString + "/";
  1086.             foreach (var item in SavableDoubles)
  1087.             {
  1088.                 SaveString = SaveString + Math.Round(item.Val,2) + "^";
  1089.             }
  1090.  
  1091.             //Iterates Through Bools
  1092.             SaveString = SaveString + "/";
  1093.             foreach (var item in SavableBools)
  1094.             {
  1095.                 SaveString = SaveString + item.Val + "^";
  1096.             }
  1097.  
  1098.             //Clears Lists To Free Up Memory Allocation
  1099.             //(Cannot properly finalise)
  1100.             //SavableStrings.Clear();
  1101.             //SavableInts.Clear();
  1102.             //SavableVectors.Clear();
  1103.             //SavableDoubles.Clear();
  1104.             //SavableBools.Clear();
  1105.             return SaveString;
  1106.         }
  1107.         void DeSerializer(string Input)
  1108.         {
  1109.             //Splits Input Into Sections
  1110.             String[] SplitInput = Input.Split('/');
  1111.             Echo(Input);
  1112.  
  1113.             //Throw.Vals Error If Cannot Split
  1114.             if (SplitInput.Length < 5)
  1115.             { Echo("Error During DeSerialization"); return; }
  1116.  
  1117.             //Exits If Grid ID is not equal to current
  1118.             if (SplitInput[0] != Me.CubeGrid.EntityId + "")
  1119.             { Echo("New Grid, Serialization Cancelled"); return; }
  1120.  
  1121.             //Splits Strings And Assigns
  1122.             string[] SplitStrings = SplitInput[1].Split('^');
  1123.             for (int i = 0; i < SavableStrings.Count; i++)
  1124.             {
  1125.                 SavableStrings[i].Val = SplitStrings[i];
  1126.             }
  1127.  
  1128.             //Splits Ints And Assigns
  1129.             string[] SplitInts = SplitInput[2].Split('^');
  1130.             for (int i = 0; i < SavableInts.Count; i++)
  1131.             {
  1132.                 SavableInts[i].Val = int.Parse(SplitInts[i]);
  1133.             }
  1134.  
  1135.             //Splits 3DVectors And Assigns
  1136.             string[] SplitVectors = SplitInput[3].Split('^');
  1137.             for (int i = 0; i < SavableVectors.Count; i++)
  1138.             {
  1139.                 Vector3D.TryParse(SplitVectors[i], out SavableVectors[i].Val);
  1140.             }
  1141.  
  1142.             //Splits Doubles And Assigns
  1143.             string[] SplitDoubles = SplitInput[4].Split('^');
  1144.             for (int i = 0; i < SavableDoubles.Count; i++)
  1145.             {
  1146.                 SavableDoubles[i].Val = double.Parse(SplitDoubles[i]);
  1147.             }
  1148.  
  1149.             //Splits Bools And Assigns
  1150.             string[] SplitBools = SplitInput[5].Split('^');
  1151.             for (int i = 0; i < SavableBools.Count; i++)
  1152.             {
  1153.                 SavableBools[i].Val = bool.Parse(SplitBools[i]);
  1154.             }
  1155.  
  1156.         }
  1157.  
  1158.         #endregion
Advertisement
Add Comment
Please, Sign In to add comment