EzPlugins

TransmutePlugin

Feb 19th, 2025 (edited)
166
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 14.14 KB | None | 0 0
  1. using Turbo.Plugins.Default;
  2. using System;
  3. using System.Text;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using System.Windows.Forms;
  7. using SharpDX.DirectInput;
  8. using System.Runtime.InteropServices;
  9. using System.Text.RegularExpressions;
  10. using System.Drawing;
  11.  
  12. namespace Turbo.Plugins.Ez
  13. {
  14.     public class TransmutePlugin : BasePlugin, IKeyEventHandler, IInGameTopPainter
  15.     {
  16.         public bool Debug { get; set; } = false;
  17.         private static IntPtr D3Hwnd = IntPtr.Zero;
  18.         [DllImport("USER32.DLL")]
  19.         private static extern IntPtr FindWindow(string ClassName, string WindowText);
  20.         [DllImport("USER32.DLL")]
  21.         private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
  22.  
  23.         private static IntPtr MakeLParam(int x, int y)
  24.         {
  25.             return (IntPtr)(y << 16 | (x & 65535));
  26.         }
  27.  
  28.         public void mouseClickUiE(Keys key, IUiElement uie) // D3Hwnd
  29.         {
  30.             if (uie.Visible)
  31.             {
  32.                 IntPtr lParam = MakeLParam((int)(uie.Rectangle.X + uie.Rectangle.Width * 0.5f), (int)(uie.Rectangle.Y + uie.Rectangle.Height * 0.5f));
  33.                 if (key == Keys.LButton)
  34.                 {
  35.                     SendMessage(D3Hwnd, 513U, (IntPtr)1, lParam);
  36.                     SendMessage(D3Hwnd, 514U, (IntPtr)1, lParam);
  37.                 }
  38.                 else if (key == Keys.RButton)
  39.                 {
  40.                     SendMessage(D3Hwnd, 516U, (IntPtr)2, lParam);
  41.                     SendMessage(D3Hwnd, 517U, (IntPtr)2, lParam);
  42.                 }
  43.             }
  44.         }
  45.  
  46.         public void mouseRClickItem(IItem item) // D3Hwnd
  47.         {
  48.             var rect = Hud.Inventory.GetItemRect(item);
  49.             if (rect != System.Drawing.RectangleF.Empty)
  50.             {
  51.                 IntPtr lParam = MakeLParam((int)(rect.X + rect.Width/2.0f), (int)(rect.Y + rect.Height/2.0f));
  52.                 SendMessage(D3Hwnd, 516U, (IntPtr)2, lParam);
  53.                 SendMessage(D3Hwnd, 517U, (IntPtr)2, lParam);
  54.             }
  55.         }
  56.  
  57.         protected IUiElement TransmuteDialog;
  58.         protected IUiElement PageNumber;
  59.         protected IUiElement TransmuteButton;
  60.         protected IUiElement RecipeButton;
  61.         protected IUiElement FillButton;
  62.         protected IUiElement PrevButton;
  63.         protected IUiElement NextButton;
  64.         protected IUiElement AcceptBlinker;
  65.  
  66.  
  67.         private List<IItem> listItemsOrd { get; set; }
  68.         private SharpDX.DirectWrite.TextLayout layout { get; set; } = null;
  69.         private Point lastItemPoint { get; set; } = Point.Empty;
  70.         private IItem lastItem { get; set; } = null;
  71.         private int[] enabledRecipes { get; set; } = new int[] {2, 3, 7, 8, 9};
  72.         private int[] enabledPages { get; set; } = new int[] {1, 2, 3, 6, 7, 8, 9};
  73.  
  74.         private bool doCube { get; set; } = false;
  75.         private bool StopNow { get; set; } = false;
  76.         private int numRecipe { get; set; } = 0;
  77.         private int stepRecipe { get; set; } = 0;
  78.         private long msLapseAction { get; set; } = 0;
  79.         private long msLapseMin { get; set; } = 50;
  80.         private string NamePlugin { get; } = "[TransmutePlugin] ";
  81.  
  82.         public bool IgnoreInventoryLockArea { get; set; }
  83.         public IKeyEvent ToggleKeyEvent { get; set; }
  84.  
  85.         public IBrush ItemHighlightBrush { get; set; }
  86.         public IFont InfoFont { get; set; }
  87.  
  88.         public string TextAvailable { get; set; }
  89.         public string TextNotAvailable { get; set; }
  90.         public string TextProcessing { get; set; }
  91.         public string TextNoMats { get; set; }
  92.         public string TextNoItems { get; set; }
  93.  
  94.         public TransmutePlugin()
  95.         {
  96.             Enabled = true;
  97.         }
  98.  
  99.         public override void Load(IController hud)
  100.         {
  101.             base.Load(hud);
  102.  
  103.             TextAvailable = "Press {0} to Start.";      // {0} => Hotkey
  104.             TextNotAvailable = "Unavailable, lock area missing.";
  105.             TextProcessing = "Recipe {0} of {1} is being processed.";   // {0} => Number recipe , {1} => Total recipes
  106.             TextNoMats = "You don't have the required mats.";
  107.             TextNoItems = "No items in inventory to process.";
  108.             ToggleKeyEvent = Hud.Input.CreateKeyEvent(true, Key.F3, controlPressed: false, altPressed: false, shiftPressed: false); // Hotkey
  109.             IgnoreInventoryLockArea = false;    // If false -> Lock area required in the inventory for recipe 2. If true -> Ignore if you have defined (or not) a lock area in the inventory.
  110.  
  111.             ItemHighlightBrush = Hud.Render.CreateBrush(255, 200, 200, 100, -1.6f);
  112.             InfoFont = Hud.Render.CreateFont("tahoma", 8, 255, 200, 200, 0, true, false, 255, 0, 0, 0, true);
  113.  
  114.             PageNumber = Hud.Render.RegisterUiElement("Root.NormalLayer.Kanais_Recipes_main.LayoutRoot.PageControls.page_number", TransmuteDialog, null);
  115.             TransmuteDialog = Hud.Render.RegisterUiElement("Root.NormalLayer.vendor_dialog_mainPage.transmute_dialog", null, null);
  116.             TransmuteButton = Hud.Render.RegisterUiElement("Root.NormalLayer.vendor_dialog_mainPage.transmute_dialog.LayoutRoot.transmute_button", TransmuteDialog, null);
  117.             RecipeButton = Hud.Render.RegisterUiElement("Root.NormalLayer.vendor_dialog_mainPage.transmute_dialog.LayoutRoot.recipe_button", TransmuteDialog, null);
  118.             FillButton = Hud.Render.RegisterUiElement("Root.NormalLayer.Kanais_Recipes_main.LayoutRoot.button_fill_currencies", TransmuteDialog, null);
  119.             NextButton = Hud.Render.RegisterUiElement("Root.NormalLayer.Kanais_Recipes_main.LayoutRoot.PageControls.page_next", TransmuteDialog, null);
  120.             PrevButton = Hud.Render.RegisterUiElement("Root.NormalLayer.Kanais_Recipes_main.LayoutRoot.PageControls.page_previous", TransmuteDialog, null);
  121.             AcceptBlinker = Hud.Render.RegisterUiElement("Root.NormalLayer.vendor_dialog_mainPage.transmute_dialog.LayoutRoot.AcceptBlinker", TransmuteDialog, null);
  122.  
  123.             D3Hwnd = FindWindow("D3 Main Window Class", null); // D3Hwnd = FindWindow(null, "Diablo III");
  124.         }
  125.  
  126.         public void OnKeyEvent(IKeyEvent keyEvent)
  127.         {
  128.             if (keyEvent.IsPressed && ToggleKeyEvent.Matches(keyEvent))
  129.             {
  130.                 if (Hud.Game.IsInTown && Hud.Inventory.InventoryMainUiElement.Visible && PageNumber.Visible)
  131.                 {
  132.                     if (doCube)
  133.                     {
  134.                         StopNow = true;
  135.                     }
  136.                     else
  137.                     {
  138.                         var match  = Regex.Match(PageNumber.ReadText(Encoding.UTF8, true),  @"([0-9]+)(/|(\sиз\s)|(쪽\s/\s))([0-9]+)");
  139.                         if (match.Success && int.TryParse(match.Groups[1].Value, out var num) && enabledRecipes.Contains(num))
  140.                         {
  141.                             if (num != 2 || IgnoreInventoryLockArea || (Hud.Inventory.InventoryLockArea.Width > 0 && Hud.Inventory.InventoryLockArea.Height > 0))
  142.                             {
  143.                                 if (checkMatsRequired(num))
  144.                                 {
  145.                                     mouseClickUiE(Keys.RButton, PageNumber);
  146.                                     var items = GetItemsForRecipe(num);
  147.                                     if (items.Any())
  148.                                     {
  149.                                         numRecipe = num;
  150.                                         stepRecipe = 0;
  151.                                         lastItem = null;
  152.                                         lastItemPoint = Point.Empty;
  153.                                         listItemsOrd = items.ToList();
  154.                                         listItemsOrd.Sort((a, b) =>
  155.                                         {
  156.                                             var r = a.InventoryX.CompareTo(b.InventoryX);
  157.                                             if (r == 0) r = a.InventoryY.CompareTo(b.InventoryY);
  158.                                             return r;
  159.                                         });
  160.                                         StopNow = false;
  161.                                         doCube = true;
  162.                                     }
  163.                                 }
  164.                             }
  165.                         }
  166.                     }
  167.                 }
  168.             }
  169.         }
  170.  
  171.         private bool checkMatsRequired(int numRecipe)
  172.         {
  173.             switch (numRecipe)
  174.             {
  175.                 case 2: return (Hud.Game.Me.Materials.ForgottenSoul > 49) && (Hud.Game.Me.Materials.KhanduranRune > 4) && (Hud.Game.Me.Materials.CaldeumNightShade > 4) && (Hud.Game.Me.Materials.ArreatWarTapestry > 4) && (Hud.Game.Me.Materials.CorruptedAngelFlesh > 4) && (Hud.Game.Me.Materials.WestmarchHolyWater > 4);
  176.                 case 3: return (Hud.Game.Me.Materials.ReusableParts > 49) && (Hud.Game.Me.Materials.ArcaneDust > 49) && (Hud.Game.Me.Materials.VeiledCrystal > 49) && (Hud.Game.Me.Materials.DeathsBreath > 24);
  177.                 case 7: return (Hud.Game.Me.Materials.ReusableParts > 99);
  178.                 case 8: return (Hud.Game.Me.Materials.ArcaneDust > 99);
  179.                 case 9: return (Hud.Game.Me.Materials.VeiledCrystal > 99);
  180.                 default: return false;
  181.             }
  182.         }
  183.  
  184.         private IEnumerable<IItem> GetItemsForRecipe(int numRecipe)
  185.         {
  186.             switch (numRecipe)
  187.             {
  188.                 case 2: return Hud.Inventory.ItemsInInventory.Where(i => i.SnoItem.Kind == ItemKind.loot && i.IsLegendary && !i.Unidentified && i.AncientRank < 2 && !i.SnoItem.IsEthereal && (!i.IsInventoryLocked || IgnoreInventoryLockArea)
  189.                                                                         && i.StatList.FirstOrDefault(s => s.Id == "IsCrafted#1048575")?.DoubleValue != 1 && Hud.Game.Me.ArmorySets.FirstOrDefault(armorySet => armorySet?.ContainsItem(i) == true) == null
  190.                                                                         && i.SnoItem.MainGroupCode != "gems_unique" && i.SnoItem.MainGroupCode != "riftkeystone" && !i.SnoItem.Code.StartsWith("P72_Soulshard") && i.SnoItem.NameEnglish != "Hellforge Ember"
  191.                                                                     );
  192.                 case 3: return Hud.Inventory.ItemsInInventory.Where(i => i.SnoItem.Kind == ItemKind.loot && i.IsRare && i.StatList.FirstOrDefault(s => s.Id == "Requirement#57")?.DoubleValue == 70);
  193.                 case 7: return Hud.Inventory.ItemsInInventory.Where(i => i.SnoItem.Kind == ItemKind.loot && (i.IsRare || i.IsMagic));
  194.                 case 8: return Hud.Inventory.ItemsInInventory.Where(i => i.SnoItem.Kind == ItemKind.loot && (i.IsRare || (i.IsNormal && !i.AccountBound)));
  195.                 case 9: return Hud.Inventory.ItemsInInventory.Where(i => i.SnoItem.Kind == ItemKind.loot && (i.IsMagic || (i.IsNormal && !i.AccountBound)));
  196.  
  197.                 default: return Enumerable.Empty<IItem>();
  198.             }
  199.         }
  200.  
  201.         public void PaintTopInGame(ClipState clipState)
  202.         {
  203.             if (clipState != ClipState.Inventory || !Hud.Game.IsInGame || !Hud.Game.IsInTown || !Hud.Inventory.InventoryMainUiElement.Visible) return;
  204.             if (PageNumber.Visible)
  205.             {
  206.                 int numPageCurrent;
  207.                 var match  = Regex.Match(PageNumber.ReadText(Encoding.UTF8, true), @"([0-9]+)(/|(\sиз\s)|(쪽\s/\s))([0-9]+)");
  208.                 if (!match.Success || !int.TryParse(match.Groups[1].Value, out numPageCurrent))
  209.                 {
  210.                     numPageCurrent = 0;
  211.                 }
  212.  
  213.                 if (doCube)
  214.                 {
  215.                     if (Hud.Game.CurrentRealTimeMilliseconds > msLapseAction)
  216.                     {
  217.                         msLapseAction = Hud.Game.CurrentRealTimeMilliseconds + msLapseMin;
  218.                         if (enabledPages.Contains(numPageCurrent))
  219.                         {
  220.                             if (AcceptBlinker.Visible)
  221.                             {
  222.                                 msLapseAction += 100;
  223.                                 mouseClickUiE(Keys.LButton, AcceptBlinker);
  224.                                 stepRecipe = 1;
  225.                             }
  226.                             else
  227.                             {
  228.                                 if (numRecipe == numPageCurrent)
  229.                                 {
  230.                                     if (StopNow) doCube = false;
  231.                                     else if (TransmuteButton.AnimState == 51)
  232.                                     {
  233.                                         if (stepRecipe == 0 || stepRecipe == 4)
  234.                                         {
  235.                                             mouseClickUiE(Keys.LButton, PrevButton);
  236.                                         }
  237.                                         else  if (stepRecipe == 1 || stepRecipe == 2) // Fill // 2,3 =>  lastItem != null always // remove (list) does not cause exceptions if the value does not exist
  238.                                         {
  239.                                             if (checkMatsRequired(numRecipe))
  240.                                             {
  241.                                                 if (numRecipe == 2 && stepRecipe == 1 && lastItem != null)
  242.                                                 {
  243.                                                     var itemAux = Hud.Inventory.ItemsInInventory.FirstOrDefault(a => a.InventoryX == lastItemPoint.X && a.InventoryY == lastItemPoint.Y);
  244.                                                     if (itemAux != null && itemAux.Seed != lastItem.Seed)   // item has changed
  245.                                                     {
  246.                                                         if (itemAux.IsLegendary && itemAux.AncientRank == 0)
  247.                                                         {
  248.                                                             listItemsOrd.Insert(0,itemAux);  // the new item is legendary, not ancient or primal => add to list
  249.                                                         }
  250.                                                     }
  251.                                                 }
  252.                                                 if (listItemsOrd.Any())
  253.                                                 {
  254.                                                     var newItem = listItemsOrd.First();
  255.                                                     if (newItem.SeenInInventory)
  256.                                                     {
  257.                                                         if (lastItem != newItem)    // first
  258.                                                         {
  259.                                                             lastItem = newItem;
  260.                                                             lastItemPoint = new Point(lastItem.InventoryX, lastItem.InventoryY);
  261.                                                             stepRecipe = 2;
  262.                                                         }
  263.                                                         else                        // second
  264.                                                         {
  265.                                                             stepRecipe = 3;
  266.                                                         }
  267.                                                         mouseClickUiE(Keys.LButton, FillButton);
  268.                                                         mouseRClickItem(lastItem);
  269.                                                     }
  270.                                                     else
  271.                                                     {
  272.                                                         listItemsOrd.Remove(newItem);
  273.                                                         lastItem = null;
  274.                                                     }
  275.                                                 }
  276.                                                 else doCube = false;
  277.                                             }
  278.                                             else doCube = false;
  279.                                         }
  280.                                         else // stepRecipe == 3 // fill fail
  281.                                         {
  282.                                             stepRecipe = 0;
  283.                                             listItemsOrd.Remove(lastItem);
  284.                                             lastItem = null;
  285.                                         }
  286.                                     }
  287.                                     else if (TransmuteButton.AnimState != 52)
  288.                                     {
  289.                                         if (stepRecipe == 2 || stepRecipe == 3)
  290.                                         {
  291.                                             listItemsOrd.Remove(lastItem);
  292.                                             mouseClickUiE(Keys.LButton, TransmuteButton);
  293.                                             stepRecipe = 4;
  294.                                         }
  295.                                         else
  296.                                         {
  297.                                             mouseClickUiE(Keys.LButton, PrevButton);
  298.                                         }
  299.                                         msLapseAction += 150;
  300.                                     }
  301.                                 }
  302.                                 else
  303.                                 {
  304.                                     mouseClickUiE(Keys.LButton, (numPageCurrent < numRecipe)? NextButton : PrevButton);
  305.                                     stepRecipe = 1;
  306.                                 }
  307.                             }
  308.                         }
  309.                         else doCube = false;
  310.                     }
  311.  
  312.                     foreach (var item in listItemsOrd)
  313.                     {
  314.                         var itemRect = Hud.Inventory.GetItemRect(item);
  315.                         if (itemRect != System.Drawing.RectangleF.Empty) ItemHighlightBrush.DrawRectangle(itemRect);
  316.                     }
  317.                     layout = InfoFont.GetTextLayout(NamePlugin + String.Format(TextProcessing, numRecipe, match.Success?match.Groups[5].Value:"?"));
  318.                 }
  319.                 else
  320.                 {
  321.                     if (enabledRecipes.Contains(numPageCurrent))
  322.                     {
  323.                         if (numPageCurrent == 2 && !IgnoreInventoryLockArea && (Hud.Inventory.InventoryLockArea.Width == 0 || Hud.Inventory.InventoryLockArea.Height == 0))
  324.                         {
  325.                             layout = InfoFont.GetTextLayout(NamePlugin + TextNotAvailable);
  326.                         }
  327.                         else
  328.                         {
  329.                             var items =  GetItemsForRecipe(numPageCurrent);
  330.                             if (items.Any())
  331.                             {
  332.                                 foreach (var item in items)
  333.                                 {
  334.                                     var itemRect = Hud.Inventory.GetItemRect(item);
  335.                                     if (itemRect != System.Drawing.RectangleF.Empty)    ItemHighlightBrush.DrawRectangle(itemRect);
  336.                                 }
  337.                                 if (checkMatsRequired(numPageCurrent))
  338.                                 {
  339.                                     layout = InfoFont.GetTextLayout(NamePlugin + String.Format(TextAvailable, ToggleKeyEvent.ToString()));
  340.                                 }
  341.                                 else layout = InfoFont.GetTextLayout(NamePlugin + TextNoMats);
  342.                             }
  343.                             else layout = InfoFont.GetTextLayout(NamePlugin + TextNoItems);
  344.                         }
  345.                     }
  346.                     else layout = null;
  347.                 }
  348.                 if (layout != null)
  349.                 {
  350.                     InfoFont.DrawText(layout, TransmuteDialog.Rectangle.X + (TransmuteDialog.Rectangle.Width * 0.056f), TransmuteDialog.Rectangle.Y + (TransmuteDialog.Rectangle.Height * 0.088f));
  351.                 }
  352.             }
  353.             else if (doCube)
  354.             {
  355.                 doCube = false;
  356.             }
  357.         }
  358.     }
  359. }
Advertisement
Add Comment
Please, Sign In to add comment