Advertisement
jarppaaja

SalvageItems

Jun 17th, 2019
1,630
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 16.11 KB | None | 0 0
  1. // SalvageItems.cs "$Revision: 2502 $" "$Date: 2019-08-17 10:11:50 +0300 (la, 17 elo 2019) $"
  2. // https://www.ownedcore.com/forums/diablo-3/turbohud/turbohud-community-plugins/792083-intl-jarjar-salvageitems.html
  3. // https://pastebin.com/E9RhzxhT
  4. // https://www.icy-veins.com/d3/legendary-item-salvage-guide
  5. using System.Collections.Generic;
  6. using System.Linq;
  7. using SharpDX;
  8. using SharpDX.Direct2D1;
  9. using Turbo.Plugins.Default;
  10.  
  11. namespace Turbo.Plugins.JarJar.DefaultUI
  12. {
  13.     public enum BuildKind : uint
  14.     {
  15.         Class = 0,      // => ClassBrush
  16.         Other = 1,      // => OtherBrush
  17.         Special = 2,    // => SpecialBrush
  18.         None = 3,       // => DarkenBrush
  19.     }
  20.  
  21.     public class SalvageItems : BasePlugin, IInGameTopPainter
  22.     {
  23.         public bool SkipLoN { get; set; } = false;              // Ignore LoN builds.
  24.  
  25.         public bool HighlightInventory { get; set; } = true;    // Draw a coloured rectable around item type in bottom-right item rect corner.
  26.         public IBrush ClassBrush { get; set; }                  // Build item is for current class.
  27.         public IBrush OtherBrush { get; set; }                  // Build item is for other class.
  28.         public IBrush SpecialBrush { get; set; }                // Build item without class, like folower items and extra special items.
  29.         public float OffsetTop { get; set; } = 18f;             // Hard coded for 1200 screen height.
  30.         public float OffsetBottom { get; set; } = 2f;
  31.  
  32.         public bool HighlightLegendary { get; set; } = true;    // Extra highlight for legendary items
  33.         public bool HighlightAncient { get; set; } = false;     // Extra highlight for ancient and primary items
  34.         public IBrush HighlightBrush { get; set; }
  35.         public float HighlightOffset { get; set; } = 1.5f;
  36.  
  37.         public bool CheckItems { get; set; } = true;                    // Mark items for easier detection what to salvage.
  38.         public bool SkipJewelryCheck { get; set; } = true;
  39.         public string CheckItemIndicator1 { get; set; } = "\u272A";     // ✪ circled white star (more than one item with same main stat)
  40.         public string CheckItemIndicator2 { get; set; } = "\u272A";     // ✪ circled white star (more than one item with same main stat and only in Inventory)
  41.         public string SingleLegendary { get; set; } = "\u25C7";         // ◇ white diamond (really the only item found)
  42.         public string SingleAncient { get; set; } = "\u29BF";           // ⦿ circled bullet (really the only item found)
  43.         public string SkippedJewelryIndicator { get; set; } = "\u2724"; // ✤ Jewelry ambiguous marker.
  44.         public string SameCountPrefix { get; set; } = "+";              // Prefix for similar items in stash.
  45.         public float FontMargin { get; set; } = 3f;                     // Item rect marker offset from top-right.
  46.  
  47.         public IFont CheckItemFont1 { get; set; }
  48.         public IFont CheckItemFont2 { get; set; }
  49.         public IFont SameCountFont { get; set; }
  50.         public IFont SingleItemFont { get; set; }
  51.         public IFont SkippedJewelryFont { get; set; }
  52.  
  53.         public bool DarkenInventory { get; set; } = true;
  54.         public bool DarkenStash { get; set; } = true;
  55.         public IBrush DarkenBrush { get; set; }
  56.  
  57.         public string[] ExtraSpecialItems { get; set; } = {     // These are considered like build items but without a specific build!
  58.             "Broken Crown",         // Gem farming.
  59.             "Hellfire Amulet",      // Special item for certain builds.
  60.             "Leoric's Signet",      // XP/leveling ring
  61.             "Hellfire Ring",        // XP/leveling ring
  62.         };
  63.  
  64.         public string[] NoDarkenItems { get; set; } = {         // Do not darken for these as they are useful!
  65.             "Puzzle Ring",
  66.             "Bovine Bardiche",
  67.         };
  68.  
  69.         private Dictionary<string, Build[]> heroBuilds;
  70.  
  71.         public SalvageItems() { Enabled = true; Order = 1000; }
  72.  
  73.         public override void Load(IController hud)
  74.         {
  75.             base.Load(hud);
  76.  
  77.             ClassBrush = createBrush(Color.OrangeRed);
  78.             OtherBrush = createBrush(Color.GreenYellow, alpha: 200);
  79.             SpecialBrush = createBrush(Color.MediumPurple);
  80.             HighlightBrush = createBrush(Color.Silver, dash: DashStyle.Dash);
  81.  
  82.             CheckItemFont1 = createFont("arial", 9, Color.DodgerBlue, bold: true, shadow: true);
  83.             CheckItemFont2 = createFont("arial", 9, Color.LightSeaGreen, bold: true, shadow: true);
  84.             SameCountFont = createFont("arial", 9, Color.DarkOrange, bold: true, shadow: true);
  85.             SingleItemFont = createFont("arial", 9, Color.Gold, bold: true, shadow: true);
  86.             SkippedJewelryFont = createFont("arial", 9, Color.LightSkyBlue, bold: true, shadow: true);
  87.  
  88.             DarkenBrush = Hud.Render.CreateBrush(148, 38, 38, 38, 0);
  89.  
  90.             heroBuilds = new SalvageItemsData().HeroBuilds;
  91.             foreach (var itemName in ExtraSpecialItems)
  92.             {
  93.                 heroBuilds.Add(itemName, new Build[] { new Build(HeroClass.None, itemName) });
  94.             }
  95.         }
  96.  
  97.         private IBrush createBrush(Color textColor, float brushWidth = -1f, DashStyle dash = DashStyle.Solid, int alpha = 255)
  98.         {
  99.             return Hud.Render.CreateBrush(alpha, textColor.R, textColor.G, textColor.B, brushWidth, dash);
  100.         }
  101.  
  102.         private IFont createFont(string fontFamily, float size, Color textColor, bool bold = false, bool shadow = false)
  103.         {
  104.             if (shadow)
  105.                 return Hud.Render.CreateFont(fontFamily, size, textColor.A, textColor.R, textColor.G, textColor.B, bold, false, 220, 032, 032, 032, true);
  106.             return Hud.Render.CreateFont(fontFamily, size, textColor.A, textColor.R, textColor.G, textColor.B, bold, false, true);
  107.         }
  108.  
  109.         public void PaintTopInGame(ClipState clipState)
  110.         {
  111.             if (clipState != ClipState.Inventory)
  112.                 return;
  113.             if (!Hud.Game.IsInTown || Hud.Render.UiHidden || Hud.Game.MapMode == MapMode.WaypointMap || Hud.Game.MapMode == MapMode.ActMap || Hud.Game.MapMode == MapMode.Map)
  114.                 return;
  115.  
  116.             var stashTab = Hud.Inventory.SelectedStashTabIndex;
  117.             var stashPage = Hud.Inventory.SelectedStashPageIndex;
  118.             var stashTabAbs = stashTab + (stashPage * Hud.Inventory.MaxStashTabCountPerPage);
  119.  
  120.             var items = Hud.Game.Items.Where(x => x.Location == ItemLocation.Inventory || x.Location == ItemLocation.Stash);
  121.             foreach (var item in items)
  122.             {
  123.                 if (item.Location == ItemLocation.Stash)
  124.                 {
  125.                     var tabIndex = item.InventoryY / 10;
  126.                     if (tabIndex != stashTabAbs)
  127.                         continue;
  128.                 }
  129.                 if (!item.IsLegendary)
  130.                     continue;
  131.                 if (item.SnoItem.Kind == ItemKind.gem)
  132.                     continue;
  133.                 if (item.SnoItem.Kind == ItemKind.craft)
  134.                     continue;
  135.                 if (item.SnoItem.Kind == ItemKind.uberstuff)
  136.                     continue;
  137.                 if (item.SnoItem.MainGroupCode == "potion" || item.SnoItem.MainGroupCode == "healthpotions")
  138.                     continue;
  139.                 if (item.SnoItem.MainGroupCode == "gems_unique")
  140.                     continue;
  141.                 if (item.SnoItem.MainGroupCode == "consumable")
  142.                     continue;
  143.                 if (item.SnoItem.MainGroupCode == "horadriccache")
  144.                     continue;
  145.                 var rect = Hud.Inventory.GetItemRect(item);
  146.                 if (rect != System.Drawing.RectangleF.Empty)
  147.                 {
  148.                     var buildKind = BuildKind.None;
  149.                     if (heroBuilds.TryGetValue(item.SnoItem.NameEnglish, out var builds))
  150.                     {
  151.                         var build = SkipLoN
  152.                             ? builds.FirstOrDefault(x => x.HeroClass == Hud.Game.Me.HeroClassDefinition.HeroClass && x.BuildNames.Count(y => y.StartsWith("LoN ")) == 0)
  153.                             : builds.FirstOrDefault(x => x.HeroClass == Hud.Game.Me.HeroClassDefinition.HeroClass);
  154.                         if (build != null)
  155.                         {
  156.                             buildKind = BuildKind.Class;
  157.                         }
  158.                         else
  159.                         {
  160.                             buildKind = builds.Any(x => x.HeroClass == HeroClass.None) ? BuildKind.Special : BuildKind.Other;
  161.                         }
  162.                     }
  163.                     if (buildKind == BuildKind.None)
  164.                     {
  165.                         DarkenItem(item, rect);
  166.                     }
  167.                     if (HighlightInventory && buildKind != BuildKind.None)
  168.                     {
  169.                         HighlightItem(item, rect, buildKind);
  170.                     }
  171.                 }
  172.             }
  173.         }
  174.  
  175.         private void HighlightItem(IItem item, System.Drawing.RectangleF rect, BuildKind buildKind)
  176.         {
  177.             if (item.CaldesannRank == 0)
  178.             {
  179.                 var brush = (IBrush)null;
  180.                 switch (buildKind)
  181.                 {
  182.                     case BuildKind.Class:
  183.                         brush = ClassBrush;
  184.                         break;
  185.                     case BuildKind.Other:
  186.                         brush = OtherBrush;
  187.                         break;
  188.                     case BuildKind.Special:
  189.                         brush = SpecialBrush;
  190.                         break;
  191.                     default:
  192.                         return;
  193.                 }
  194.                 if ((item.AncientRank == 0 && HighlightLegendary) || (item.AncientRank > 0 && HighlightAncient))
  195.                 {
  196.                     HighlightBrush.DrawRectangle(rect.Right - OffsetTop - HighlightOffset, rect.Bottom - OffsetTop - HighlightOffset, OffsetTop - OffsetBottom + (2 * HighlightOffset), OffsetTop - OffsetBottom + (2 * HighlightOffset));
  197.                 }
  198.                 brush.DrawRectangle(rect.Right - OffsetTop, rect.Bottom - OffsetTop, OffsetTop - OffsetBottom, OffsetTop - OffsetBottom);
  199.             }
  200.             if (CheckItems)
  201.             {
  202.                 if (SkipJewelryCheck && (item.SnoItem.MainGroupCode == "amulet" || item.SnoItem.MainGroupCode == "ring"))
  203.                 {
  204.                     // Skip checking until we know what we want!
  205.                     showMarker(rect, SkippedJewelryIndicator, SkippedJewelryFont);
  206.                 }
  207.                 else
  208.                 {
  209.                     var showCheckMark = false;
  210.                     var matchedItems = new List<IItem>();
  211.                     var ranks = countItemRanks(item, ref matchedItems);
  212.                     if (ranks[2] > 0)
  213.                     {
  214.                         if (item.AncientRank >= 1)
  215.                         {
  216.                             if (item.Location == ItemLocation.Inventory)
  217.                             {
  218.                                 // Check ancient/primal!
  219.                                 showCheckMark = true;
  220.                             }
  221.                             else
  222.                             {
  223.                                 // Count ancient/primal!
  224.                                 showMarker(rect, SameCountPrefix + (ranks[1] + ranks[2]).ToString(), SameCountFont);
  225.                             }
  226.                         }
  227.                     }
  228.                     else if (ranks[1] > 0)
  229.                     {
  230.                         if (item.AncientRank == 1)
  231.                         {
  232.                             if (item.Location == ItemLocation.Inventory)
  233.                             {
  234.                                 // Check ancient.
  235.                                 showCheckMark = true;
  236.                             }
  237.                             else
  238.                             {
  239.                                 // Count ancient.
  240.                                 showMarker(rect, SameCountPrefix + ranks[1].ToString(), SameCountFont);
  241.                             }
  242.                         }
  243.                     }
  244.                     else if (ranks[0] > 0)
  245.                     {
  246.                         if (item.AncientRank == 0)
  247.                         {
  248.                             // We have only legendaries.
  249.                             showCheckMark = true;
  250.                         }
  251.                     }
  252.                     else
  253.                     {
  254.                         if (item.Location == ItemLocation.Inventory)
  255.                         {
  256.                             showMarker(rect, item.AncientRank == 0 ? SingleLegendary : SingleAncient, SingleItemFont);
  257.                         }
  258.                     }
  259.                     if (showCheckMark)
  260.                     {
  261.                         var nonInventory = matchedItems.Any(x => x.Location != ItemLocation.Inventory);
  262.                         if (nonInventory)
  263.                         {
  264.                             showMarker(rect, CheckItemIndicator1, CheckItemFont1);
  265.                         }
  266.                         else
  267.                         {
  268.                             showMarker(rect, CheckItemIndicator2, CheckItemFont2);
  269.                         }
  270.                     }
  271.                 }
  272.             }
  273.         }
  274.  
  275.         private void DarkenItem(IItem item, System.Drawing.RectangleF rect)
  276.         {
  277.             if (item.CaldesannRank > 0)
  278.             {
  279.                 return;
  280.             }
  281.             if (NoDarkenItems.Contains(item.SnoItem.NameEnglish))
  282.             {
  283.                 HighlightBrush.DrawRectangle(rect.Right - OffsetTop, rect.Bottom - OffsetTop, OffsetTop - OffsetBottom, OffsetTop - OffsetBottom);
  284.                 return;
  285.             }
  286.             DarkenBrush.DrawRectangle(rect.X, rect.Y, rect.Width, rect.Height);
  287.         }
  288.  
  289.         private void showMarker(System.Drawing.RectangleF rect, string symbol, IFont font)
  290.         {
  291.             // Top right corner.
  292.             if (!string.IsNullOrEmpty(symbol))
  293.             {
  294.                 var layout = font.GetTextLayout(symbol);
  295.                 font.DrawText(layout, rect.Right - FontMargin - layout.Metrics.Width, rect.Top + FontMargin);
  296.             }
  297.         }
  298.  
  299.         private IItemPerfection getMainStat(IItem item)
  300.         {
  301.             if (item != null && !item.Unidentified && item.Perfections != null)
  302.             {
  303.                 foreach (var perfection in item.Perfections)
  304.                 {
  305.                     if (perfection.Attribute.Code == "Dexterity_Item" || perfection.Attribute.Code == "Intelligence_Item" || perfection.Attribute.Code == "Strength_Item")
  306.                     {
  307.                         return perfection;
  308.                     }
  309.                 }
  310.             }
  311.             return null;
  312.         }
  313.  
  314.         private bool hasMainStat(IItemPerfection mainStat ,IItem item)
  315.         {
  316.             if (item != null && !item.Unidentified && item.Perfections != null)
  317.             {
  318.                 foreach (var perfection in item.Perfections)
  319.                 {
  320.                     if (perfection.Attribute.Code == "Dexterity_Item" || perfection.Attribute.Code == "Intelligence_Item" || perfection.Attribute.Code == "Strength_Item")
  321.                     {
  322.                         return mainStat == null ? false : mainStat.Attribute.Code == perfection.Attribute.Code;
  323.                     }
  324.                 }
  325.             }
  326.             return mainStat == null ? true : false;
  327.         }
  328.  
  329.         private int[] countItemRanks(IItem item, ref List<IItem> items)
  330.         {
  331.             // We always match main stat!
  332.             var ranks = new int[] { 0, 0, 0 };
  333.             var itemMainStat = getMainStat(item);
  334.             foreach (var x in Hud.Game.Items)
  335.             {
  336.                 if (x.SnoItem.NameEnglish == item.SnoItem.NameEnglish &&
  337.                     x.Location != ItemLocation.Merchant && x.Location != ItemLocation.Floor &&
  338.                     x.Seed != item.Seed && hasMainStat(itemMainStat, x))
  339.                 {
  340.                     ranks[x.AncientRank] += 1;
  341.                     items.Add(x);
  342.                 }
  343.             }
  344.             return ranks;
  345.         }
  346.     }
  347. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement