Skip to content

Instantly share code, notes, and snippets.

@ChuckSavage
Created November 3, 2018 08:35
Show Gist options
  • Select an option

  • Save ChuckSavage/e5e26a0b3764c679a100481bf74c97ad to your computer and use it in GitHub Desktop.

Select an option

Save ChuckSavage/e5e26a0b3764c679a100481bf74c97ad to your computer and use it in GitHub Desktop.

Revisions

  1. ChuckSavage created this gist Nov 3, 2018.
    301 changes: 301 additions & 0 deletions battery_charge_and_drill_load_level.cs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,301 @@
    // dco.pe/vsb

    const float MinValueToActivateRedLights = 5000f;
    const float VolumeOfDrills = 33750f; // small ship drill (large is 234375f)

    public Program()
    {
    Runtime.UpdateFrequency = UpdateFrequency.Update100;
    }

    public class InventoryItem
    {
    private readonly IMyInventoryItem _this;

    public InventoryItem(IMyInventoryItem item)
    {
    _this = item;
    }

    public float Amount { get { return (float)_this.Amount; } }

    public bool IsOre { get { return (bool)(_IsOre ?? (_IsOre = _this.Content.TypeId.ToString().EndsWith("Ore"))); } }
    bool? _IsOre;

    public string ItemType { get { return _ItemType ?? (_ItemType = _this.Content.SubtypeId.ToString()); } }
    string _ItemType;

    public IMyInventoryItem This { get { return _this; } }
    }

    public class Inventory
    {
    private readonly IMyInventory _this;

    public Inventory(IMyInventory inventory)
    {
    _this = inventory;
    }

    public float CurrentMass { get { return (float)_this.CurrentMass; } }

    /// <summary>
    /// Multiplied by 1000 to get the value you see in game
    /// </summary>
    public float CurrentVolume { get { return ((float)_this.CurrentVolume) * 1000f; } }

    public List<InventoryItem> Items() { return _this.GetItems().Select(item => new InventoryItem(item)).ToList(); }
    //public List<VRage.Game.Entity.MyPhysicalInventoryItem> Items2() { return _this.GetItems(); }

    public float MaxVolume { get { return ((float)_this.MaxVolume); } }

    public IMyInventory This { get { return _this; } }
    }

    public class CargoContainers
    {
    private readonly IMyTerminalBlock _this;

    public CargoContainers(IMyTerminalBlock cargoBlock)
    {
    _this = cargoBlock;
    }

    //IMyInventory inventoryB = (containerB as IMyInventoryOwner).GetInventory(0)
    public Inventory Inventory { get { return _Inventory ?? (_Inventory = new Inventory((_this as IMyInventoryOwner).GetInventory(0))); } }
    Inventory _Inventory;

    public bool IsDrill { get { return IsType<IMyShipDrill>(); } }

    public bool IsType<T>() where T : IMyTerminalBlock
    {
    try
    {
    var t = (T)_this;
    return true;
    }
    catch { return false; }
    //return null != _this as T;
    }

    public string Name { get { return _this.CustomName; } }

    public IMyTerminalBlock This { get { return _this; } }
    }

    void Main(string argument)
    {
    // block declarations
    string ERR_TXT = "";
    List<IMyTerminalBlock> v0 = new List<IMyTerminalBlock>();
    GridTerminalSystem.GetBlocksOfType<IMyBatteryBlock>(v0, filterThis);
    if (v0.Count == 0)
    {
    ERR_TXT += "no Battery blocks found\n";
    }
    List<IMyTerminalBlock> v1 = new List<IMyTerminalBlock>();
    GridTerminalSystem.GetBlocksOfType<IMyInteriorLight>(v1, filterThis);
    if (v1.Count == 0)
    {
    ERR_TXT += "no Interior Light blocks found\n";
    }
    List<IMyTerminalBlock> v2 = new List<IMyTerminalBlock>();
    GridTerminalSystem.GetBlocksOfType<IMyShipDrill>(v2, filterThis);
    if (v2.Count == 0)
    {
    ERR_TXT += "no Drill blocks found\n";
    }

    // display errors
    if (ERR_TXT != "")
    {
    Echo("Script Errors:\n" + ERR_TXT + "(make sure block ownership is set correctly)");
    if (ERR_TXT.Contains("Drill"))
    return;
    }

    if (v0.Count > 0)
    {
    // battery logic
    bool result0v0 = true;
    for (int i = 0; i < v0.Count; i++)
    {

    if (!(getExtraFieldFloat(v0[i], "Max Stored Power:.*Stored power: (\\d+\\.?\\d*) (\\w?)Wh") >= 1050000 && v0[i].GetValueBool("Recharge") == true))
    {
    //Echo("break power loop");
    result0v0 = false;
    break;
    }
    }
    if (result0v0)
    SetInteriorLightsColor(v1, 0, 255, 0); // set green
    else
    SetInteriorLightsColor(v1, 255, 255, 255); // set white
    }
    else
    SetInteriorLightsColor(v1, 255, 255, 255); // set white


    // Balance the drills inventories
    //List<IMyTerminalBlock> blocks = new List<IMyTerminalBlock>();
    //GridTerminalSystem.GetBlocksOfType<IMyCargoContainer>(blocks); // get all cargo container type blocks
    List<CargoContainers> drills = v2.Select(block => new CargoContainers(block)).ToList();
    //Echo("CargoContainers : " + cargos.Count.ToString());
    //cargos.ForEach(cargo => Echo("Container : " + cargo.Name));
    //var drills = cargos.Where(cargo => cargo.IsDrill).ToList();
    //Echo("Drills : " + drills.Count.ToString());
    //var d = drills.First();
    //var firstItem = d.Inventory.GetItems().FirstOrDefault();
    //Echo(firstItem.GetType().FullName);

    // Balance the drills if there are more than one drill
    if (drills.Count > 1)
    {
    drills = drills.OrderBy(drill => drill.Inventory.CurrentMass).ToList();
    var maxDrill = drills.Last();

    // balance if volume would trigger red lights if not balanced
    if (maxDrill.Inventory.CurrentVolume >= MinValueToActivateRedLights)
    {
    var minDrill = drills.First(); // was already sorted getting the maxDrill
    float diff = maxDrill.Inventory.CurrentMass - minDrill.Inventory.CurrentMass;
    diff /= 2; // diff = diff / 2;

    Echo("MaxDrill:" + maxDrill.Inventory.CurrentMass.ToString());
    Echo("MinDrill:" + minDrill.Inventory.CurrentMass.ToString());
    Echo("Half Diff:" + diff.ToString());

    if (diff >= 1f)
    {

    float max = 0;
    int maxIndex = 0;
    var maxItems = maxDrill.Inventory.Items();
    InventoryItem maxItem = null;
    for (int i = 0; i < maxItems.Count; i++)
    {
    maxItem = maxItems[i];
    if (maxItem.Amount > max)
    {
    max = maxItem.Amount;
    maxIndex = i;
    }
    }
    //Echo("MaxItemAmount:" + max.ToString());
    //Echo("MaxItemIndex:" + maxIndex.ToString());

    // amount = lesser of item.Amount and diff
    var amount = (VRage.MyFixedPoint)Math.Min(diff, maxItem.Amount);
    // parameters for this are: TransferItemTo(IMyInventory destination, int itemIndex, Nullable&lt;int> targetItemIndex, Nullable&lt;bool> tryToStack, Nullable&lt;MyFixedPoint> amount);
    maxDrill.Inventory.This.TransferItemTo(minDrill.Inventory.This, maxIndex, null, true, amount);
    }
    }
    //var firstItem = maxDrill.Inventory.This.GetItems().FirstOrDefault();
    //Echo(firstItem?.Content.SubtypeId.ToString() ?? "No Items");
    //Echo(firstItem.GetType().FullName);
    }



    //float maxDrillVolume = v2
    // .Select(d => (IMyShipDrill)d)
    // .Select(I => I.GetInventory(0))
    // .Select(inv => ((float)inv.CurrentVolume) * 1000)
    // .Max();

    float maxDrillVolume = v2.Max(drill => (float)((IMyShipDrill)drill).GetInventory(0).CurrentVolume * 1000);
    //Echo(fs(maxDrillVolume));
    if (maxDrillVolume >= MinValueToActivateRedLights)
    {
    float percentInDrill = maxDrillVolume / VolumeOfDrills;
    float sumDrillVolume = 255 * percentInDrill; // to get percent value of 255 not 100
    //Echo("sumDrillVolume : "+ fs(sumDrillVolume));
    float nonRed = sumDrillVolume % 255; // 0 to 255 color
    nonRed = 255 - nonRed; // flip the value to be 255 to 0
    //Echo(fs(nonRed));

    SetInteriorLightsColor(v1, 255, (int)nonRed, (int)nonRed); // set steadily increasing red color
    }
    else
    Echo("Drills empty");

    // This used to sum the value in the drills.
    // Not as effective, since drills don't share their volumes. One could fill up, and you'd
    // then be wasting that ore it continued to mine.

    //bool result2v2 = false;
    //float drillVolume, sumDrillVolume;
    //sumDrillVolume = 0;

    // for (int i = 0; i < v2.Count; i++) {
    //drillVolume = (float)((IMyShipDrill)v2[i]).GetInventory(0).CurrentVolume;
    // // maxDrillVolume = Math.Max(maxDrillVolume, )

    // drillVolume *= 1000;
    ////Echo("Drill "+v2[i].CustomName +" : "+ fs(drillVolume));
    ////drillVolume = 5001; // 1/6th full
    ////drillVolume = 11250; // 1/3rd full
    ////drillVolume = 16875; // 1/2 full
    ////drillVolume = 25312; // 3/4th full
    //sumDrillVolume += drillVolume;
    ////Echo("sumDrillVolume : "+ fs(sumDrillVolume));
    //if(!result2v2 && (drillVolume > 5000f))
    // result2v2 = true;
    // }
    // if(result2v2) {
    ////Echo("Drills : "+ v2.Count.ToString());
    ////Echo("sumDrillVolume : "+ fs(sumDrillVolume));
    //float totalVolume = 33750f * v2.Count;
    ////Echo("totalVolume : "+fs(totalVolume));
    //sumDrillVolume /= totalVolume;
    //sumDrillVolume *= 255; // to get percent value of 255 not 100
    ////Echo("sumDrillVolume : "+ fs(sumDrillVolume));
    //float nonRed = sumDrillVolume % 255; // 0 to 255 color
    //nonRed = 255 - nonRed; // flip the value to be 255 to 0
    ////Echo(fs(nonRed));
    //for(int i = 0; i < v1.Count; i++) {
    // v1[i].SetValueColor("Color", new Color(255, (int)nonRed, (int)nonRed));
    //}
    // }
    // else
    //Echo("Drills empty");
    }

    void SetInteriorLightsColor(List<IMyTerminalBlock> list, int red, int green, int blue)
    {
    list.ForEach(light => light.SetValueColor("Color", new Color(red, green, blue)));
    }

    string fs(float f)
    {
    int i = (int)f;
    return i.ToString();
    }

    const string MULTIPLIERS = ".kMGTPEZY";

    bool filterThis(IMyTerminalBlock block)
    {
    return block.CubeGrid == Me.CubeGrid;
    }

    float getExtraFieldFloat(IMyTerminalBlock block, string regexString)
    {
    System.Text.RegularExpressions.Regex regex = new System.Text.RegularExpressions.Regex(regexString, System.Text.RegularExpressions.RegexOptions.Singleline);
    float result = 0.0f;
    double parsedDouble;
    System.Text.RegularExpressions.Match match = regex.Match(block.DetailedInfo);
    if (match.Success)
    {
    if (Double.TryParse(match.Groups[1].Value, out parsedDouble))
    {
    result = (float)parsedDouble;
    }
    if (MULTIPLIERS.IndexOf(match.Groups[2].Value) > -1)
    {
    result = result * (float)Math.Pow(1000.0, MULTIPLIERS.IndexOf(match.Groups[2].Value));
    }
    }
    return result;
    }