1. This forum is obsolete and read-only. Feel free to contact us at support.keenswh.com

Req: I need a simple piston speed adjustment script

Discussion in 'Programming (In-game)' started by AutoMcD, Jun 14, 2015.

Thread Status:
This last post in this thread was made more than 31 days old.
  1. AutoMcD

    AutoMcD Senior Engineer

    Messages:
    2,369
    I'm building a ship which will have several pistons strung together to make a mining boom. Like this:
    [​IMG]

    The one I'm building right now is bigger, like 10-15 pistons. And the piston speeds stack! so while drilling I want them set to a very low speed such as .01, but while extending or retracting it can be much faster, like .15. But the last few feet retracting it should be slow because pistons stopping are kinda bouncy and scary.

    So I'm envisioning this:
    LCD panel named "Drill Boom Config" where you can play adjust the travel, drilling, and parking speeds
    2 sensors. 1st is at the end to detect asteroids. this hits a timer to start the drills and whatever else is going on down there. The script will detect this to set piston speed.
    2nd sensor detects the ship, script will use it to set the pistons to parking speed

    When neither sensor is active we can bump the pistons to travel speed because we are all impatient and that asteroid is actually way further away than we parked. :)
     
  2. Mauzen

    Mauzen Trainee Engineer

    Messages:
    75
    Ive got a huge pistondrill control script which is pretty close to what you need. Its ugly as hell but does its job. Right now it just sets two speeds: drilling and retracting, but this can be changed easily. It is combined with a range finder PB to get the distance to the asteroid. That distance could be used to change from travelling to drilling speed, right now its just decorative.
    Comes with an ore counter and some fancy displays. But it definitely needs a rework to make it somehow useful for other drill setups, Ill see if I can do that soon enough.

    https://steamcommunity.com/sharedfiles/filedetails/?id=461108113
     
    • Like Like x 1
  3. DjSmellyCat

    DjSmellyCat Trainee Engineer

    Messages:
    21
    So just to check, you want the drill to detect the asteroid and then extend at drilling speed. you want to be able to extend or retract the rig at travel speed but have it slow to parking speed when nearly retracted?
    Also, the resolution on piston velocity is only 0.1 m/s so this is the slowest each piston can travel.
     
  4. Mauzen

    Mauzen Trainee Engineer

    Messages:
    75
    Thats the minimum shown speed in the interface, as it only show the first decimal. But in fact you can set lower speeds in the interface or via PB, its a normal float value.
     
  5. DjSmellyCat

    DjSmellyCat Trainee Engineer

    Messages:
    21
    Really?/ because i tried 0.01 and it rounded down to 0.
     
  6. d4rky1989

    d4rky1989 Apprentice Engineer

    Messages:
    332
    Made the same experience with thrusters. Min value is 1% (0.01) of max value. Everything below 0.01 is set to 0
     
  7. AutoMcD

    AutoMcD Senior Engineer

    Messages:
    2,369
    ctrl-click on the slider and you can type in very low numbers. The displayed value rounds it to the nearest 0.1 but the value stays. It might say 0.0 but the pistons are still moving!

    I want the pistons to have high speed unless ship or asteroid is detected at the drill head (2 sensors right on the back of the drills). One is for slower drilling speed if asteroid detected, other is for safe parking speed if ship is detected.
    The only reason I'm using separate sensors for this is because the detection field for asteroid will be as wide as the drill head, but the ship detection will have to be an odd shaped box so that the pistons themselves don't trigger it.

    Sounds like it would work for me! I think what I'm looking for is simpler but I certainly like the status displays. I'm looking forward to it! :)

    BTW there is a little contest going on where nearly every ship has one of these drill booms, so if you can knock it out you'll have an instant fan club. ;)
    https://forums.keenswh.com/threads/contest-from-concept-to-creation-june-prospector.7361441/
     
  8. DjSmellyCat

    DjSmellyCat Trainee Engineer

    Messages:
    21
    Last edited: Jun 14, 2015
    • Like Like x 1
  9. THEphil

    THEphil Trainee Engineer

    Messages:
    48
    Neat idea. I slapped the following together https://steamcommunity.com/sharedfiles/filedetails/?id=461239300
    It's not going to be very good code, but it seemed to work.

    Create a group called "DrillBoom" and add your pistons, drills and sensors.

    Create a timer block with the delay of one, set the programming block to run and the timer block to start.

    Set one sensor to detect only asteroids. When an asteroid is detected by this sensor the boom will extend.
    Set another sensor to detect players, small ships, large ships and stations. This sensor will retract if an object is detected. It would be good to place this sensor on the tip of the boom with your drills.

    On a menu bar or button panel add the programming block with the argument "extend" to extend the boom and the programming block with the argument "retract" to retract the boom.

    Change the following variables to adjust speed.
    const float EXTENDVELOCITY = .05f;
    const float RETRACTVELOCITY = -1.5f;

    Code:
    // ---------------------------------------------------------------------------//
    // --- Information Section ---------------------------------------------------//
    // ---------------------------------------------------------------------------//
    //  **** Run script via timer set to 1 second. ****
    //  **** Create a group called DrillBoom in the SE client ****
    //  The group should contains all of your boom pistons, drills and two sensors
    //  Add one sensor to your ship, it should only detect asteroids
    //  Add another sensor to the drills at the end of your boom it should detect players, small ships, large ships, and stations.
    //
    // General Information (algorithm) :
    //  Reads a group defined by BOOMGROUP and finds, pistons, drills and sensors.
    //  Boom extends when sensor detects asteroid
    //  Program block arguments "extend" and "retract" can control boom.
    // Author(s) : Phil Allen phil@hilands.com
    // Last Edited By: phil@hilands.com
    // Version : 2015061403
    // Copyright (C) 2015  Philip Allen
    //  This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
    //  This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
    //  You should have received a copy of the GNU Lesser General Public License along with this program.  If not, see <https://www.gnu.org/licenses/>.
    //============================================================================//
    // Variables to Edit
    //============================================================================//
    int intStayExtended = 5; // set to 0 to keep boom extended.
    const string BOOMGROUP = "DrillBoom";
    const float MAXVELOCITY = 1.5f; // Max Extend speed when sensors clear.
    const float MINVELOCITY = .05f; // Extending speed when sensor is hot.
    const int IGNORESAFETYRANGE = 10; // Ignore safety on large ships in meters. 10m = 1 piston extended length. This will make it so the pistons don't retract if host ship is detected.
    
    // display debugging info to text panel.
    DisplayFinder Display = new DisplayFinder(); // Reference to Object created outside Main()
    const string DISPLAYNAME = "Text Panel Science Deck";
    
    // Variables for system.
    bool FoundDisplay = false;
    int intExtendedTicker = 0; // ticker for extension time.
    List<IMyTerminalBlock> BoomBlocks;
    List<IMyTerminalBlock> PistonBlocks=new List<IMyTerminalBlock>();
    List<IMyTerminalBlock> DrillBlocks=new List<IMyTerminalBlock>();
    List<IMyTerminalBlock> SensorBlocks=new List<IMyTerminalBlock>();
    //List<IMySensorBlock> SensorBlocks=new List<IMySensorBlock>();
    bool boolIsExtending = false;
    bool boolIsExtended = false;
    bool boolIsRetracting = false;
    bool boolIsRetracted = true;
    string strDebug = "";
    string strVerbose = "";
    //============================================================================//
    // Main
    //============================================================================//
    void Main(string argument)
    {
       strDebug = "";
       //if(!Display.SetDisplay(DISPLAYNAME, GridTerminalSystem)){Echo(Display.strError); return;}
       if(Display.SetDisplay(DISPLAYNAME, GridTerminalSystem))FoundDisplay = true;
    /*
       strDebug += "Extending "+ boolIsExtending.ToString()+"\n";
       strDebug += "Extended "+ boolIsExtended.ToString()+"\n";
       strDebug += "Retracting "+ boolIsRetracting.ToString()+"\n";
       strDebug += "Retracted "+ boolIsRetracted.ToString()+"\n";
    */
       // find group and store in Blocks
       if(PistonBlocks.Count == 0)
       {
         strDebug += "Detecting Blocks in Group";
         BoomBlocks = GetBlockGroupsWithName(BOOMGROUP);
         if (BoomBlocks == null)
         {
           Echo ("No group '"+BOOMGROUP+"' found");
           return;
         }
         for (int i=0; i < BoomBlocks.Count; i++)
         {
           if (BoomBlocks[i].BlockDefinition.ToString().Contains("MyObjectBuilder_ExtendedPistonBase"))
             PistonBlocks.Add(BoomBlocks[i]);
           else if (BoomBlocks[i].BlockDefinition.ToString().Contains("MyObjectBuilder_Drill"))
             DrillBlocks.Add(BoomBlocks[i]);
           else if (BoomBlocks[i].BlockDefinition.ToString().Contains("MyObjectBuilder_SensorBlock"))
             SensorBlocks.Add((IMySensorBlock)BoomBlocks[i]);
         }
         if (PistonBlocks.Count == 0)
           strVerbose += "No Piston Blocks found in group '"+BOOMGROUP+"', your boom isn't a boom!";
         if (DrillBlocks.Count == 0)
           strVerbose += "No Drill Blocks found in group '"+BOOMGROUP+"', you will need to active your drills manually";
         if (SensorBlocks.Count == 0)
           strVerbose += "No Sensor Blocks found in group '"+BOOMGROUP+"', Safety and automation is offline";
       }
    
       strDebug+="Extended Range: '"+GetTotalExtendedRange().ToString()+"'m\n";
    
       // check for arguments
       if (argument.ToLower()=="retract")
       {
         ClearBooleans();
         boolIsRetracting = true;
       }
       else if (argument.ToLower()=="extend")
       {
         ClearBooleans();
         boolIsExtending = true;
       }
       // if we are retracting just retract do nothing else.
       if (boolIsRetracting)
       {
         Retract();
       }
       else if (boolIsRetracted)
       {
         Retracted();
         // check sensors to see if we should extend.
         if(SensorBlocks.Count > 0)
         {
           // extend if asteroid found
           for (int i=0; i < SensorBlocks.Count; i++)
           {
             if (((IMySensorBlock)SensorBlocks[i]).IsActive)
             {
               //strDebug += ((IMySensorBlock)SensorBlocks[i]).LastDetectedEntity.ToString()+"\n";
               if(((IMySensorBlock)SensorBlocks[i]).LastDetectedEntity.ToString().Contains("MyVoxelMap"))
               {
                   ClearBooleans();
                   boolIsExtending = true;
               }
             }
           }
         }
       }
       else if (boolIsExtending)
       {
         // do the sensor safety check, just in case there is a player, base, or small ship in front of the boom.
         for (int i=0; i < SensorBlocks.Count; i++)
         {
           if (((IMySensorBlock)SensorBlocks[i]).IsActive)
           {
             if(!((IMySensorBlock)SensorBlocks[i]).LastDetectedEntity.ToString().Contains("MyVoxelMap") && GetTotalExtendedRange() > IGNORESAFETYRANGE)
    ///&& ((IMySensorBlock)SensorBlocks[i]).LastDetectedEntity.ToString().Contains("Grid_D_Large")
             {
               if(!CheckRetracted())
               {
                 ClearBooleans();
                 boolIsRetracting = true;
               }
             }
           }
         }
         Extend();
       }
       else // IsExtended
       {
         // we should retract after a certain count;
         if (intStayExtended != 0)
         {
           if (intExtendedTicker == intStayExtended)
           {
             ClearBooleans();
             boolIsRetracting = true;
             intExtendedTicker = 0;
           }
           else
           {
             intExtendedTicker++;
             //strDebug+= "Extended for: "+(intStayExtended-intExtendedTicker).ToString()+" seconds";
           }
         }
       }
    
       strDebug += strVerbose;
       if(FoundDisplay)
         Display.writeDisplay(strDebug);
       Echo (strDebug);
    }
    //============================================================================//
    // End Main
    //============================================================================//
    //============================================================================//
    // ClearBooleans
    //============================================================================//
    void ClearBooleans()
    {
       boolIsExtending = false;
       boolIsExtended = false;
       boolIsRetracting = false;
       boolIsRetracted = false;
    }
    //============================================================================//
    // Extend
    //============================================================================//
    void Extend()
    {
         strDebug += "Boom is extending\n";
         // turn drills on
         if (DrillBlocks.Count > 0)
         {
           if(!DrillBlocks[0].GetValue<bool>("OnOff"))
           {
             for (int i=0; i < DrillBlocks.Count; i++)
             {
               DrillBlocks[i].GetActionWithName("OnOff_On").Apply(DrillBlocks[i]);
             }
           }
         }
         boolIsExtended = true;
         float fltExtendSpeed = MAXVELOCITY*1;
         // determine speed
         if (SensorBlocks.Count > 0)
         {
           for (int i=0; i < SensorBlocks.Count; i++)
           {
             if (((IMySensorBlock)SensorBlocks[i]).IsActive)
               fltExtendSpeed = MINVELOCITY*1;
           }
         }
         // extend pistons
         if (PistonBlocks.Count > 0)
         {
           for (int i=0; i < PistonBlocks.Count; i++)
           {
             if(((IMyPistonBase)PistonBlocks[i]).CurrentPosition !=10)
             {
               //if(((IMyPistonBase)PistonBlocks[i]).Velocity < .1)
                 //((IMyPistonBase)PistonBlocks[i]).GetActionWithName("IncreaseVelocity").Apply(PistonBlocks[i]);
               if(((IMyPistonBase)PistonBlocks[i]).Velocity != fltExtendSpeed);
                 ((IMyPistonBase)PistonBlocks[i]).SetValueFloat("Velocity", fltExtendSpeed);
               strDebug+= "Extending Piston '"+PistonBlocks[i].CustomName+"' at '"+((IMyPistonBase)PistonBlocks[i]).Velocity+"' Velocity.\nCurrently at "+((IMyPistonBase)PistonBlocks[i]).CurrentPosition+"/10\n";
               boolIsExtended = false;
               return; //bounce out to extend one piston at a time.
             }
             //strDebug += ((IMyPistonBase)PistonBlocks[i]).CustomName+" "+((IMyPistonBase)PistonBlocks[i]).Velocity.ToString()+"\n";
             //strDebug += "Pos: "+((IMyPistonBase)PistonBlocks[i]).CurrentPosition+"\n";
           }
         }
         if (boolIsExtended)
         {
           boolIsExtending = false;
         }
    }
    //============================================================================//
    // Retract
    //============================================================================//
    void Retract()
    {
       strDebug += "Boom is retracting, all actions halted until retraction complete\n";
       // Retract pistons
       boolIsRetracted = true;
       // set slower speed when sensor hot
    
       float fltRetractSpeed = MAXVELOCITY*-1;
       if (SensorBlocks.Count > 0)
       {
         for (int i=0; i < SensorBlocks.Count; i++)
         {
           if (((IMySensorBlock)SensorBlocks[i]).IsActive)
             fltRetractSpeed = MINVELOCITY*-1;
         }
       }
    
       if (PistonBlocks.Count > 0)
       {
         for (int i=0; i < PistonBlocks.Count; i++)
         {
           if(((IMyPistonBase)PistonBlocks[i]).CurrentPosition !=0)
           {
             //((IMyPistonBase)PistonBlocks[i]).GetActionWithName("Retract").Apply(PistonBlocks[i]);
             //if(((IMyPistonBase)PistonBlocks[i]).Velocity > -1.5)
               //((IMyPistonBase)PistonBlocks[i]).GetActionWithName("DecreaseVelocity").Apply(PistonBlocks[i]);
             if(((IMyPistonBase)PistonBlocks[i]).Velocity != fltRetractSpeed);
               ((IMyPistonBase)PistonBlocks[i]).SetValueFloat("Velocity", fltRetractSpeed);
               strDebug+= "Retracting Piston '"+PistonBlocks[i].CustomName+"' at '"+((IMyPistonBase)PistonBlocks[i]).Velocity+"' Velocity.\nCurrently at "+((IMyPistonBase)PistonBlocks[i]).CurrentPosition+"/10\n";
             boolIsRetracted = false;
           }
         }
       }
       if (boolIsRetracted)
       {
         Echo("Here");
         //Retracted();
         ClearBooleans();
         boolIsRetracted = true;
       }
           //strDebug += ((IMyPistonBase)PistonBlocks[i]).CustomName+" "+((IMyPistonBase)PistonBlocks[i]).Velocity.ToString()+"\n";
           //strDebug += "Pos: "+((IMyPistonBase)PistonBlocks[i]).CurrentPosition+"\n";
    }
    //============================================================================//
    // CheckRetracted
    //============================================================================//
    bool CheckRetracted()
    {
       bool boolRetracted = true;
       if (PistonBlocks.Count > 0)
       {
         for (int i=0; i < PistonBlocks.Count; i++)
         {
           if(((IMyPistonBase)PistonBlocks[i]).CurrentPosition !=0)
           {
             if (((IMyPistonBase)PistonBlocks[i]).CurrentPosition != 0)
               boolRetracted = false;
           }
         }
       }
       return boolRetracted;
    }
    //============================================================================//
    // GetTotalExtendedRange
    //============================================================================//
    float GetTotalExtendedRange()
    {
       float fltTotalExtendedRange = 0f;
       if (PistonBlocks.Count > 0)
       {
         for (int i=0; i < PistonBlocks.Count; i++)
         {
           fltTotalExtendedRange +=((IMyPistonBase)PistonBlocks[i]).CurrentPosition;
         }
       }
       return fltTotalExtendedRange;
    }
    //============================================================================//
    // Retracted
    //============================================================================//
    void Retracted()
    {
       strDebug += "Boom is retracted awaiting input\n";
       // turn off drills
      
       if (DrillBlocks.Count > 0)
       {
         if(DrillBlocks[0].GetValue<bool>("OnOff"))
         {
           for (int i=0; i < DrillBlocks.Count; i++)
           {
             DrillBlocks[i].GetActionWithName("OnOff_Off").Apply(DrillBlocks[i]);
           }
         }
       }
       // incase program was restarted midway
       if (PistonBlocks.Count > 0)
       {
         if(((IMyPistonBase)PistonBlocks[0]).CurrentPosition !=0)
         {
           ClearBooleans();
           boolIsRetracting=true;
         }
       }
    }
    
    
    //============================================================================//
    // GetBlockGroupsWithName
    //============================================================================//
    List<IMyTerminalBlock> GetBlockGroupsWithName(string strGroupName)
    {
       List<IMyBlockGroup> BlockGroups = GridTerminalSystem.BlockGroups;
       for (int i=0; i< BlockGroups.Count; i++)
       {
         if (BlockGroups[i].Name == strGroupName)
           return BlockGroups[i].Blocks;
       }
       return null;
    }
    
    
    
    //============================================================================//
    // DisplayFinder Class!
    //============================================================================//
    // General Information (algorithm) :
    //  Finds a display, does error checking and writes data to it.
    //  If Multiple Displays find size of screens
    // Code Example :
    //  DisplayFinder Display = new DisplayFinder(); // place this line outside Main()
    //  if(!Display.SetDisplay("LCD Panel", GridTerminalSystem)){Echo(Display.strDebug); return;}
    //  Display.writeDisplay("Display message");
    // Author(s) : Phil Allen phil@hilands.com
    // Last Edited By: phil@hilands.com
    // Version : 2015061302
    // Copyright (C) 2015  Philip Allen
    //  This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
    //  This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
    //  You should have received a copy of the GNU Lesser General Public License along with this program.  If not, see <https://www.gnu.org/licenses/>.
    public class DisplayFinder
    {
       //========================================================================//
       // DisplayFinder variables
       //========================================================================//
       //public IMyTextPanel DisplayBlock;
       public IMyTerminalBlock DisplayBlock;
       public string strDebug = "";
       public string strError = "";
       IMyGridTerminalSystem _GridTerminalSystem = null;
       string strDisplayName ="";
       bool boolExactName=false;
       bool boolMultiDisplay=false; // Not implemented. Stuck on thinking this through..
       /*
         MutliDisplay issues. Does the information scroll top to bottom, what if you want a wall 3x3?vs 1x3.
         Sorting via alphabatized list is easy enough creating a new sorted list.
         What if the font sizes are all different? (How many lines per LCD, width of each LCD, what about types normal/wide)
         // force font sizes to match first found LCD in group.
       */
       string strDisplayType="lcd"; // LCD - text/lcd, Block - others will change CustomName to be displayed on HUD.
       //========================================================================//
       // DisplayFinder Constructor - allow exact name to be pushed during instantiation
       //========================================================================//
       public DisplayFinder(bool ExactName=false)
       {
         boolExactName = ExactName;
       }
       //========================================================================//
       // DisplayFinder Gets and Sets
       //========================================================================//
       // SetExactName - for boolExactName
       public void SetExactName(bool ExactName)
       {
         boolExactName = ExactName;
       }
       // GetExactName - for boolExactName
       public bool GetExactName()
       {
         return boolExactName;
       }
       // MultiDisplay Gets/Sets
       public void SetMultiDisplay(bool MultiDisplay)
       {
         boolMultiDisplay = MultiDisplay;
       }
       public bool GetMultiDisplay()
       {
         return boolMultiDisplay;
       }
       // DisplayType Gets/Sets
       public void SetDisplayType(string strType)
       {
         strDisplayType = strType.ToLower();
       }
       public string GetDisplayType()
       {
         return strDisplayType;
       }
       //========================================================================//
       // DisplayFinder SetDisplay Method - Sets the display and does error checking.
       //  Merged with DisplayCheck
       //  Removed Constructor (DisplayFinder()) now a method so class does not have to be instantiated every time the script runs.
       //========================================================================//
       public bool SetDisplay(string strName, IMyGridTerminalSystem grid)
       {
         // reset debug and error message.
         strDebug = "";
         //strError = "";
         if(strName != strDisplayName) // check if the name matches, if code uses external variable this will force it to update.
           strDisplayName = strName;
         if(_GridTerminalSystem == null) // make sure gridterminalsystem exists, first run
           _GridTerminalSystem = grid;
         // make sure DisplayName is not empty
         if (String.IsNullOrEmpty(strDisplayName))
         {
           strError="Display Name is empty or null. Please provide the name of your display";
           return false;
         }
         // Check for display block if we haven't checked before, first make sure the display block name was not changed.
         // add workaround for cleaner HUD vs LCD.
         bool boolCheckDisplay=false;
         if (strDisplayType == "lcd")
         {
           if(DisplayBlock == null || strDisplayName != DisplayBlock.CustomName)
             boolCheckDisplay=true;
         }
         else
         {
           if(DisplayBlock == null)
             boolCheckDisplay=true;
         }
         //if(DisplayBlock == null || strDisplayName != DisplayBlock.CustomName)
         // remove check on custom name as it messes with the Show On Hud
         //if(DisplayBlock == null)
         if(boolCheckDisplay)
         {
           var DisplayBlocks = new List<IMyTerminalBlock>();
           if (boolExactName)
           {
             if(_GridTerminalSystem.GetBlockWithName(strDisplayName) == null)
             {
               strError = "No Block found with name '"+strDisplayName+"'\n";
               return false;
             }
             DisplayBlocks.Add(_GridTerminalSystem.GetBlockWithName(strDisplayName));//getblockwithname returns one block not a list.
           }
           else
             _GridTerminalSystem.SearchBlocksOfName(strDisplayName, DisplayBlocks);
           if (DisplayBlocks.Count == 1)
           {
             DisplayBlock = DisplayBlocks[0];
             // find object type
             /*
               MyObjectBuilder_TextPanel/LargeLCDPanel // Large Ship Normal LCD
               MyObjectBuilder_TextPanel/LargeLCDPanelWide // Large Ship Wide LCD
               MyObjectBuilder_TextPanel/LargeTextPanel // Large Ship TextPanel
             */
             //if (!DisplayBlock.BlockDefinition.ToString().Contains("LCDPanel") || !DisplayBlock.BlockDefinition.ToString().Contains("TextPanel"))
             if (!DisplayBlock.BlockDefinition.ToString().Contains("TextPanel"))
               strDisplayType = "block";
             return true;
           }
           else if (DisplayBlocks.Count > 1)
           {
             if(boolExactName)
             {
               strError = "Multiple matches found for a block with the name of '"+strDisplayName+"'.\n\n Change the name of your block so that it does not match the names of other blocks.\n";
             }
             else
             {
               strError = "Multiple matches found for a block with the name of '"+strDisplayName+"'.\n\n The script is currently set to  use 'SearchBlocksOfName' try adding 'if(!<object>.GetExactName()) <object>.SetExactName(true)' to your code.\n";
             }
           }
           else
             strError = "Could not find a display with the supplied name. Please validate the name of your display is '"+strDisplayName+"'";       return false;
         }
         else // We checked before and nothing changed.
           return true;
       }
       //========================================================================//
       // DisplayFinder WriteDisplay Method - Write data to display
       //  Input String to write to display
       //========================================================================//
       public void writeDisplay(string strData)
       {
         if(strDisplayType.ToLower() == "lcd")
         {
           ((IMyTextPanel)DisplayBlock).WritePublicText(strData);
           ((IMyTextPanel)DisplayBlock).ShowTextureOnScreen();
           ((IMyTextPanel)DisplayBlock).ShowPublicTextOnScreen();
         }
         else //assume user set to Block
         {
           DisplayBlock.SetCustomName(strData);
           DisplayOnHud(true);
         }
       }
       //========================================================================//
       // DisplayFinder clearDisplay Method - Clears Display
       //  Mainly used for DisplayOnHUDtype
       //========================================================================//
       public void clearDisplay()
       {
         if(strDisplayType.ToLower() == "lcd")
         {
           ((IMyTextPanel)DisplayBlock).WritePublicText("");
           ((IMyTextPanel)DisplayBlock).ShowTextureOnScreen();
           ((IMyTextPanel)DisplayBlock).ShowPublicTextOnScreen();
         }
         else //assume user set to Block
         {
           DisplayBlock.SetCustomName(strDisplayName);
           DisplayOnHud(false);
         }
       }
       //========================================================================//
       // DisplayFinder DisplayOnHUD - Sets Display Block to Display On HUD.
       //========================================================================//
       public void DisplayOnHud(bool OnOff)
       {
         if(OnOff)
           DisplayBlock.RequestShowOnHUD(true);
         else
           DisplayBlock.RequestShowOnHUD(false);
       }
    }
    //============================================================================//
    // END DisplayFinder Class!
    //============================================================================//
    
    oops part of this is broken hehe, I'll see if I can fix it.
    I didn't read the entire request, was having too much fun! Will have a few tweaks up soon.
     
    Last edited: Jun 14, 2015
    • Like Like x 1
  10. DjSmellyCat

    DjSmellyCat Trainee Engineer

    Messages:
    21
    After testing my scripts I realized they weren't quite up to scratch (more complicated than necessary and didn't activate drill heads)
    So I have added automatic control of any drill with "<drill>" in the name and simplified the design so that you only need 1 PB and 2 sensors.
    All relevant instructions are included in the script.
    If you think a screen is required, let me know and i will add support for them but i honestly don't see much use for a screen on such a small scale implementation.
    Edit: Now on Workshop https://steamcommunity.com/sharedfiles/filedetails/?id=461473798
    Code:
    /*
    ####################################################################
    #                                          Boom Drilling Control Script                                                   
    #                                                                                                                                         
    #  Allows a user to control a drilling rig mounted at the end of a series of pistons.       
    #  The user can give two commands to extend or retract the boom.                               
    #  When the drilling rig detects an asteroid, the boom extention speed is reduced       
    #  and the drills come online.                                                                                         
    #  When the user retracts the boom, the drills stop and the boom retracts at full         
    #  speed untill...                                                                                                               
    #  When the drilling rig detects the ship i.e. it is nearly retracted, the boom speed     
    #  is reduced.                                                                                                                   
    #
    #                                                     Instructions
    #
    #  Add "<drill>" the name of all pistons in the boom, the actual name doesn't matter
    #  as long as it contains "<drill>" (no quotes). To change this, edit DRILL_PISTON_ID below.
    #
    #  Do the same for all the drills, add "<drill>" somewhere in their name.
    #  To change this, edit DRILL_ID below.
    #
    #  Place a sensor and adjust it's settings so that it will detect asteroids at the appropriate
    #  distance. The sensor should be called "AsteroidSensor" or change ASTEROID_SENSOR
    #  below.
    #  In the Setup Actions menu for the sensor, set it to Run this Programmable Block with the
    #  Argument "asteroid" (no quotes)
    #
    #  Place another sensor to detect the ship when the boom is nearly retracted. This sensor
    #  should be called "ShipSensor" or change SHIP_SENSOR below.
    #  Set this sensor to Run this Programmable Block with the Argument "ship".
    #
    #  To control the boom, use a button panel or the toolbar to setup two actions.
    #  One to Run this script with the argument "extend" to extend the boom.
    #  The other with the argument "retract" Guess what that one does :P
    #
    #  You can customize the speed of the boom below:
    #
    #  TRAVEL_SPEED   => Speed the boom extends and retracts when not drilling or near
    #                                     the ship.
    #  DRILLING_SPEED => Speed at which the boom continues to extend when an asteroid
    #                                     is detected.
    #  PARKING_SPEED => Speed at which the boom continues to retract when the ship is
    #                                     detected.
    #
    #                    +========================================+
    #                        Author: James McIntosh     Last Modified: 6-14-15
    #                                 Contact: james@james-mcintosh.com
    #                    +========================================+
    ####################################################################
    */
    
    //  IDs for blocks
    //--------------------------------------------------------------------------------
    private const string DRILL_PISTON_ID = "<drill>";
    private const string DRILL_ID = "<drill>";
    private const string ASTEROID_SENSOR = "AsteroidSensor"; 
    private const string SHIP_SENSOR = "ShipSensor";
    //---------------------------------------------------------------------------------
    
    // Change these values to customize spped
    //--------------------------------------------------------
    private const float TRAVEL_SPEED = 0.5f;
    private const float DRILLING_SPEED = 0.1f; 
    private const float PARKING_SPEED = 0.1f;
    //--------------------------------------------------------
    
    List<IMyTerminalBlock> allPistons; 
    List<IMyTerminalBlock> drillPistons;
    List<IMyTerminalBlock> allDrills;
    List<IMyTerminalBlock> drillDrills;
    IMySensorBlock asteroidSensor, shipSensor;
    
    void Initialize()
    {
        allPistons = new List<IMyTerminalBlock>();
        drillPistons = new List<IMyTerminalBlock>();
        allDrills = new List<IMyTerminalBlock>();
        drillDrills = new List<IMyTerminalBlock>();
        asteroidSensor = GridTerminalSystem.GetBlockWithName(ASTEROID_SENSOR) as IMySensorBlock; 
        shipSensor = GridTerminalSystem.GetBlockWithName(SHIP_SENSOR) as IMySensorBlock;
    
        GridTerminalSystem.GetBlocksOfType<IMyPistonBase>(allPistons);
        GridTerminalSystem.GetBlocksOfType<IMyShipDrill>(allDrills);
    
    // Find the pistons the user wants to be affected by the script
        for (int i = 0; i < allPistons.Count; i++)
        {
            IMyPistonBase piston = allPistons[i] as IMyPistonBase;
            if (piston.CustomName.Contains(DRILL_PISTON_ID))
                {
                    drillPistons.Add(piston);
                }
        }
    
    // Find the drills the user wants to be affected by the script
        for (int i = 0; i < allDrills.Count; i++)
        {
            IMyShipDrill drill = allDrills[i] as IMyShipDrill;
            if (drill.CustomName.Contains(DRILL_ID))
                {
                    drillDrills.Add(drill);
                }
        }
    }
    void ExtendDrill()
    {
        for (int i = 0; i < drillPistons.Count; i++)
        {
            IMyPistonBase piston = drillPistons[i] as IMyPistonBase;
            piston.SetValueFloat("Velocity", TRAVEL_SPEED * -1);
            piston.GetActionWithName("Reverse").Apply(piston);
        }
    }
    void RetractDrill()
    {
        StopDrilling();
    
        for (int i = 0; i < drillPistons.Count; i++)
        {
            IMyPistonBase piston = drillPistons[i] as IMyPistonBase;
            piston.SetValueFloat("Velocity", TRAVEL_SPEED);
            piston.GetActionWithName("Reverse").Apply(piston);
        }
    }
    void AsteroidDetected()
    {
        StartDrilling();
    
        for (int i = 0; i < drillPistons.Count; i++) 
        {   
            IMyPistonBase piston = drillPistons[i] as IMyPistonBase;   
            piston.SetValueFloat("Velocity", DRILLING_SPEED * -1);   
            piston.GetActionWithName("Reverse").Apply(piston);   
        }
    }
    void ShipDetected()
    {
        for (int i = 0; i < drillPistons.Count; i++)   
        {   
            IMyPistonBase piston = drillPistons[i] as IMyPistonBase;   
            piston.SetValueFloat("Velocity", PARKING_SPEED);   
            piston.GetActionWithName("Reverse").Apply(piston);   
        }
    }
    void StartDrilling()
    {
        for (int i = 0; i < drillDrills.Count; i++)
        {
            IMyShipDrill drill = drillDrills[i] as IMyShipDrill;
            drill.GetActionWithName("OnOff_On").Apply(drill);
        }
    }
    void StopDrilling()
    {
        for (int i = 0; i < drillDrills.Count; i++)
        {
            IMyShipDrill drill = drillDrills[i] as IMyShipDrill;
            drill.GetActionWithName("OnOff_Off").Apply(drill);
        }
    }
    void Main(string args)
    {
        Initialize();
    
        switch (args)
        {
            case "extend":
                ExtendDrill();
            break;
            case "retract":
                RetractDrill();
            break;
            case "asteroid":
                AsteroidDetected();
            break;
            case "ship":
                ShipDetected();
            break;
        }   
    }
    
     
    Last edited: Jun 14, 2015
  11. THEphil

    THEphil Trainee Engineer

    Messages:
    48
    @DjSmellyCat
    start > run / search / or enter in explorer location bar.
    %AppData%\Roaming\SpaceEngineers\IngameScripts\local\
    rename Script_0 folder and it will change in game :)
    Both the rename from details and rename from the right window pane are acting up. You may need to close the BP list and reopen it.
     
    • Like Like x 1
  12. DjSmellyCat

    DjSmellyCat Trainee Engineer

    Messages:
    21
    Thanks for the help, Script now available on the Workshop https://steamcommunity.com/sharedfiles/filedetails/?id=461473798
     
  13. Bleuhazenfurfle

    Bleuhazenfurfle Apprentice Engineer

    Messages:
    284
    Might be a silly question... but are you guys extending one piston at a time, during the drilling phase? would think that would give much better speed control... (But didn't see any sign of doing so in my rather brief look over the code.)
     
  14. THEphil

    THEphil Trainee Engineer

    Messages:
    48
    For the one I posted https://steamcommunity.com/sharedfiles/filedetails/?id=461239300 pistons are extended one at a time but retracted all at once.
    The codes a bit sloppy so it's not easy to spot.
    In the extend method the pistons are cycled through a for loop.
    When the first piston that is not fully extended is found (position not 10)
    the velocity is changed and the code bounces out of a the loop with an early return statement.

    I can't seem to bold the return in the forums code bb element. But it has a comment //bounce out to extend one piston at a time.
    Code:
    void Extend()
    {
    ........
        // extend pistons
         if (PistonBlocks.Count > 0)
         {
           for (int i=0; i < PistonBlocks.Count; i++)
           {
             if(((IMyPistonBase)PistonBlocks[i]).CurrentPosition !=10)
             {
               //if(((IMyPistonBase)PistonBlocks[i]).Velocity < .1)
                 //((IMyPistonBase)PistonBlocks[i]).GetActionWithName("IncreaseVelocity").Apply(PistonBlocks[i]);
               if(((IMyPistonBase)PistonBlocks[i]).Velocity != fltExtendSpeed);
                 ((IMyPistonBase)PistonBlocks[i]).SetValueFloat("Velocity", fltExtendSpeed);
               strDebug+= "Extending Piston '"+PistonBlocks[i].CustomName+"' at '"+((IMyPistonBase)PistonBlocks[i]).Velocity+"' Velocity.\nCurrently at "+((IMyPistonBase)PistonBlocks[i]).CurrentPosition+"/10\n";
               boolIsExtended = false;
               return; //bounce out to extend one piston at a time.
             }
             //strDebug += ((IMyPistonBase)PistonBlocks[i]).CustomName+" "+((IMyPistonBase)PistonBlocks[i]).Velocity.ToString()+"\n";
             //strDebug += "Pos: "+((IMyPistonBase)PistonBlocks[i]).CurrentPosition+"\n";
           }
         }
    .........
    }
     
  15. AutoMcD

    AutoMcD Senior Engineer

    Messages:
    2,369
    interesting. I assumed all at once, that's how i trigger them when using non-scripted style. just set the speed very very low because they all add up.
     
  16. THEphil

    THEphil Trainee Engineer

    Messages:
    48
    @AutoMcD - Do you have the ship in OP on the workshop?
    I answered my own question looking at your creations thread, it's the Gemini II (Mobile Base) https://steamcommunity.com/sharedfiles/filedetails/?id=356938929

    FYI I updated my version of the script with a bunch of stuff. Now it's way over complicated.

    I was having issues with the docking sensor and getting the speed just right. Running the queries to the sensor via a script didn't seem to work as well as it would from a timer sensor block, e.g. it was slamming back too fast, extending the sensor just made it go out to slow. So it's now based on a defined range setting in the script where the retract setting is higher than extend to give it a little extra time between the one second settings. Hmm maybe triggering a sensor to run the script with an argument would have been better, oh well :)
    Did a bunch of other things like variables for single piston extend/return LCD displays and other things. A list of changes can be found here https://steamcommunity.com/sharedfiles/filedetails/changelog/461239300.

    The "configuration" part that needs to be done in the script is in the "Variables to Edit" section of the code.

    [​IMG]
    Simple LCD showing the extended range and speed of each piston. LCD auto resizes based on font and scrolls if you get a ton of pistons. You can kind of see in the screen shot that only one piston is extended at a time.

    [​IMG]
    You can also point the output to an antenna or other random terminal block which will auto toggle the display on hud stuff. Just remember to run the script with the argument DisplayOff if you change it!

    If you want me to upload the code to the forums or github let me know, otherwise it's in the workshop https://steamcommunity.com/sharedfiles/filedetails/?id=461239300.


    Thanks for the fun idea!
     
    Last edited: Jun 18, 2015
  17. Bleuhazenfurfle

    Bleuhazenfurfle Apprentice Engineer

    Messages:
    284
    Yush, I did miss that... coolies... also thought though it was worth emphasizing because no one had mentioned it that I'd seen, but someone had mentioned struggling to get them to go slow enough.

    And, i do have a related question... has anyone seen a difference in piston stability between pushing and pulling them all at once, and operating them one at a time?
     
  18. AutoMcD

    AutoMcD Senior Engineer

    Messages:
    2,369
    Finally got my ship far along enough to try this out. It looks a little something like this:
    [​IMG]
    [​IMG]

    Boom has 15 pistons and extends 160m.
    First go with the script was pretty rough. Things broke. I didn't even use it on rocks yet.

    The things I would tweak:
    -Pistons should all move at the same time. Every time something stops or starts it's kind of a big deal; lots of wobbly things happening. When I use piston group to move them all simultaneously it's much smoother than when your script was doing things one piston at a time. I really don't see any advantage to that complication.

    -Things are crazier when the drills are running. Twisting, etc. It should wait until the sensor detects rock, on my dry run they should not even have turned on.
    I found that putting a gyro on the drill head helps a lot! But still they should be off when moving at higher than drilling speed.

    -I may have to add dampening thrusters to reduce sway. If I go there then it should turn on the thrusters upon extend and turn them off when done.

    -The drills didn't turn off when it was done retracting. They should be off as soon as sensor says we cleared the rock and the speed goes up.

    -I have a normal grav gen and some lights that should just turn on/off with the drills. The lights came on w/ extend but the grav didn't. I'm not too good reading code but it appears you only made provision for spherical style. Maybe an extend and retract timer to turn all the random things on and off would be better? It's how I do it with just sensors.

    -Display is a little too crazy for me because of all the pistons. I want to use a single text display and not have it scrolling to show each piston (especially if changed so they all are doing same thing). The other status data is PERFECT.
    [​IMG]

    Other than that, very cool. Love the display action.

    edit:
    almost forgot about the parking gear.. needs to unlock before extending, and lock when retracted! :)
     
    Last edited: Jun 21, 2015
  19. THEphil

    THEphil Trainee Engineer

    Messages:
    48
    @AutoMcD
    https://steamcommunity.com/sharedfiles/filedetails/changelog/461239300

    All the code changes mentioned below will be in the between line ~25 and 45 in the variables to edit section looks like....
    Code:
    //============================================================================//
    // Variables to Edit
    //============================================================================//
    -Pistons
    You can change the single extend to multiple extend with the
    Code:
    const bool EXTENDONEPISTONATATIME=false;
    const bool RETRACTONEPISTONATATIME=false;
    -Drills
    Updated to only turn on when a sensor is flagged. e.g. asteroid detected. That makes sense, I have no idea what my thought process on that was, maybe that I wouldn't use a sensor????
    Not sure why they didn't turn off when retracted. "-The drills didn't turn off when it was done retracting. They should be off as soon as sensor says we cleared the rock and the speed goes up."

    -Dampening thrusters
    Updated. Add thruster to the group, they will turn on when extending and off when retracted :)I had no idea that they acted as a different ship when connected to a piston, crazy!

    -Grav Gens
    Updated. That was some weird mangling. It is now set so it turns any type of gravity gen in the group by default. Had it set to turn off any grav gens and turn on any sphericals. That's the way I like it so I put in a boolGravityMangle that I can set to true for me :)

    -Display
    Added two booleans one is to show all the pistons and the other is to turn off scrolling. Turning either of them off would probably suit your needs. If you want something else displayed on it I'd like to hear it.
    Code:
    bool boolShowDisplayIndividualPistons = false;
    bool boolScrollText = false;
    -Parking
    I was wondering how you did it with your ship, I was trying merge blocks and connectors and they just didn't seem to work. It looked like you have landing gears. I tested the landing gears and it worked on my ship! so I updated it to lock landing gears in the group when retracted and to unlock them just before they extend. It might be buggy, it doesn't validate that the landing gears are locked or unlocked, just tries to flip them on and off.
     
    • Like Like x 1
  20. AutoMcD

    AutoMcD Senior Engineer

    Messages:
    2,369
    Wow that was quick! Thank you!! :D
     
  21. AutoMcD

    AutoMcD Senior Engineer

    Messages:
    2,369
    OK I have some more testing feedback for you. :)

    [​IMG]
    My landing gear didn't unlock! D:

    Just kidding! Apparently it didn't update. Reloaded it and it worked. Fun screenshot anyway..

    So the speeds are per piston if you set EXTENDONEPISTONATATIME=false. Leaving that set to 1 makes it go FAST (15m/s total, which is a wrecking ball). Mine is set to .2 now.
    It does not total them together. It's not a problem but should be noted..

    I can't seem to get the display to work anymore, doesn't matter what those new vars are set to. ?
    It's not giving a 'screen not found' error so it sees the display but it's just blank.

    The total boom distance math is bugged, seems 2x higher than it should be.

    One of my pistons had a minimum distance of .5 set, it was just a little safety margin to keep things from banging into eachother.
    The script would not register the boom as fully retracted until I got rid of this. Is there a provision for this in the script?
    Also the slowdown distance while parking didn't seem to happen. Unless I missed it. Was expecting the last few meters while retracting to go slowly.

    Cheers!
     
  22. THEphil

    THEphil Trainee Engineer

    Messages:
    48
    @AutoMcD
    About the 2x higher. I think there is a bug with the groups and programming blocks. It's either something with the SE code when you reload a save, or add an item to a group. I'll see if I can pinpoint it and submit it as a bug. I keep thinking its something funky in the script but when I trash the group and remake it, it works fine.

    I'll try to duplicate the screen display issue, I might have broken it. I didn't to a ton of testing before posting the updated code.

    There is no checking for minimum distance/max distance settings of the piston in the script, didn't think about checking that.

    For the docking slow down. Try doubling the retract docking clearance, or set it to 20. You should be able to see it when it slows down. Set it higher if you don't see it.
    Code:
    const float EXTENDDOCKINGCLEARANCE = 3;
    const float RETRACTDOCKINGCLEARANCE = 20;
     
    Last edited: Jun 22, 2015
  23. THEphil

    THEphil Trainee Engineer

    Messages:
    48
    https://steamcommunity.com/sharedfiles/filedetails/changelog/461239300
    Checks for MinLimit/MaxLimit so it will fully extend and retract if the piston min distance and max distance are set.
    Display data is now set up for that. it will display 0m if the piston is at minimal distance 5m.

    The version I uploaded commented out the display code.

    The doubling issue is an SE issue, when I get more info I'll submit a bug report. 2 ways to fix this.
    1. re-create the group
    2. add a random block to the group, save the group, remove the block from the group, save the game.

    I wrote some code to send a list of items in a group to the detailedinfo section of the programming block so I can submit a bug.
    Code:
    const string GROUP = "DrillBoom";
    List<IMyTerminalBlock> Blocks;
    
    void Main()
    {
       Blocks = GetBlockGroupsWithName(GROUP);
       if (Blocks == null)
       {
         Echo ("No group '"+Blocks+"' found");
         return;
       }
       for (int i=0; i < Blocks.Count; i++)
       {
         //Echo(Blocks[i].ToString());
         Echo(Blocks[i].CustomName);
       }
    }
    //============================================================================//
    // GetBlockGroupsWithName
    //============================================================================//
    List<IMyTerminalBlock> GetBlockGroupsWithName(string strGroupName)
    {
       List<IMyBlockGroup> BlockGroups = GridTerminalSystem.BlockGroups;
       for (int i=0; i< BlockGroups.Count; i++)
       {
         if (BlockGroups[i].Name == strGroupName)
           return BlockGroups[i].Blocks;
       }
       return null;
    }
    /*
    Testing group duplicates
    1.
     make a group
     save the game
     reload the game - might not have to reload
     add another block to the group
     Pistons get doubled.
    2.
     From loaded game
     add item to group
     pistons, drills anything attached to pistons gets doubled.
    */
     
Thread Status:
This last post in this thread was made more than 31 days old.