// InventoryAndStashPlugin.cs "$Revision: 865 $" "$Date: 2019-01-24 18:33:04 +0200 (to, 24 tammi 2019) $" //modded by rambo99jose on 20190517@2340 using System; using System.Globalization; using System.Linq; using Turbo.Plugins; using Turbo.Plugins.Default; namespace Turbo.Plugins.JarJar.DefaultUI { public class InventoryAndStashPlugin : BasePlugin, ICustomizer, IInGameTopPainter { // NOTE that this draws to same places as original InventoryAndStashPlugin! public bool ShowImportantEnabled { get; set; } = true; public bool ShowGreenStarEnabled { get; set; } = true; public bool ShowRedStarEnabled { get; set; } = false; public bool HoradricCacheEnabled { get; set; } = true; public bool CanCubedEnabled { get; set; } = false; public string StarChar { get; set; } = "\u2605"; // black star public string FollowerChar { get; set; } = "\uD83D\uDEE1"; // shield public string RecycleChar { get; set; } = "\u267A"; // recycling symbol public string NoticeChar { get; set; } = "\u25CF"; // black circle public string CubeChar { get; set; } = "\u2622"; // radioactive sign public IFont LooksGoodFont { get; set; } public IFont LooksBadFont { get; set; } public IFont FollowerFont { get; set; } public IFont RecycleFont { get; set; } public IFont CubeFont { get; set; } public IFont NoticeFont { get; set; } public IFont AncientRankFont { get; set; } public IFont PrimalRankFont { get; set; } public IFont SocketedLegendaryGemRankFont { get; set; } public IFont HoradricCacheFont { get; set; } public IFont QuantityFont { get; set; } public Func GetItemKeepDecision; public IBrush InventoryLockBorderBrush { get; set; } //readonly StopWatch _stopper = StopWatch.StartNew(); private IWatch _stopper; public InventoryAndStashPlugin() { Enabled = true; } public void Customize() { // Disable original InventoryAndStashPlugin & Co.! Hud.TogglePlugin(false); Hud.TogglePlugin(false); } public override void Load(IController hud) { base.Load(hud); _stopper = Hud.Time.CreateAndStartWatch(); LooksGoodFont = Hud.Render.CreateFont("arial", 9, 255, 0, 255, 0, false, false, true); // Bright green (lime) LooksBadFont = Hud.Render.CreateFont("arial", 9, 255, 204, 0, 0, false, false, true); // Red FollowerFont = Hud.Render.CreateFont("arial", 7, 255, 51, 204, 166, false, false, true); // Green-blue RecycleFont = Hud.Render.CreateFont("arial", 10, 255, 255, 128, 0, true, false, true); // Orange CubeFont = Hud.Render.CreateFont("arial", 10, 128, 255, 255, 0, true, false, true); // Yellow (with alpha) NoticeFont = Hud.Render.CreateFont("arial", 11, 255, 255, 0, 255, true, false, false); // Bright violet NoticeFont.SetShadowBrush(128, 0, 0, 0, true); GetItemKeepDecision = (item) => { return item.KeepDecision; // Default behaviour is like random decisions! }; HoradricCacheFont = Hud.Render.CreateFont("tahoma", 8, 255, 255, 255, 255, false, false, false); HoradricCacheFont.SetShadowBrush(128, 0, 0, 0, true); AncientRankFont = Hud.Render.CreateFont("arial", 7, 255, 0, 0, 0, true, false, 220, 227, 153, 25, true); PrimalRankFont = Hud.Render.CreateFont("arial", 7, 255, 0, 0, 0, true, false, 180, 255, 64, 64, true); SocketedLegendaryGemRankFont = Hud.Render.CreateFont("arial", 7, 255, 0, 0, 0, true, false, false); SocketedLegendaryGemRankFont.SetShadowBrush(128, 240, 240, 64, true); QuantityFont = Hud.Render.CreateFont("tahoma", 8, 255, 200, 200, 200, false, false, false); QuantityFont.SetShadowBrush(128, 0, 0, 0, true); InventoryLockBorderBrush = Hud.Render.CreateBrush(100, 0, 150, 200, -1.6f); } private int stashPage, stashTab, stashTabAbs; private float rv; public void PaintTopInGame(ClipState clipState) { if (clipState != ClipState.Inventory) return; stashTab = Hud.Inventory.SelectedStashTabIndex; stashPage = Hud.Inventory.SelectedStashPageIndex; stashTabAbs = stashTab + stashPage * Hud.Inventory.MaxStashTabCountPerPage; rv = 32.0f / 600.0f * Hud.Window.Size.Height; if ((Hud.Inventory.InventoryLockArea.Width > 0) && (Hud.Inventory.InventoryLockArea.Height > 0)) { var rect = Hud.Inventory.GetRectInInventory(Hud.Inventory.InventoryLockArea.X, Hud.Inventory.InventoryLockArea.Y, Hud.Inventory.InventoryLockArea.Width, Hud.Inventory.InventoryLockArea.Height); InventoryLockBorderBrush.DrawRectangle(rect.X, rect.Y, rect.Width, rect.Height); } var items = Hud.Game.Items.Where(x => x.Location != ItemLocation.Merchant && x.Location != ItemLocation.Floor); foreach (var item in items) { if (item.Location == ItemLocation.Stash) { var tabIndex = item.InventoryY / 10; if (tabIndex != stashTabAbs) continue; } if ((item.InventoryX < 0) || (item.InventoryY < 0)) continue; var rect = Hud.Inventory.GetItemRect(item); if (rect == System.Drawing.RectangleF.Empty) continue; if (item.ItemsInSocket != null) DrawItemSocketedLegendaryGemRank(item, rect); if (item.AncientRank >= 1) DrawItemAncientRank(item, rect); DrawItemHoradricCache(item, rect); if (CanCubedEnabled) DrawItemCanCubed(item, rect); // New paint logic. if (item.Location == ItemLocation.Stash || item.Location == ItemLocation.Inventory) { if (item.Unidentified || !item.IsLegendary || item.SnoItem.Kind == ItemKind.gem || item.SnoItem.Kind == ItemKind.uberstuff || item.SnoItem.Kind == ItemKind.potion || item.SnoItem.MainGroupCode == "gems_unique" || item.SnoItem.MainGroupCode == "riftkeystone" || item.SnoItem.MainGroupCode == "healthpotions" || item.SnoItem.MainGroupCode == "consumable" || item.SnoItem.MainGroupCode == "horadriccache") { continue; } } if (ShowImportantEnabled || ShowGreenStarEnabled || ShowRedStarEnabled) { if ((item.SnoItem.NameEnglish == "Puzzle Ring" || item.SnoItem.NameEnglish == "Bovine Bardiche") && RecycleFont != null) { ShowStar(rect, RecycleChar, RecycleFont, false); continue; } string starChar = StarChar; bool? armorySet = null; // Check cube items only in inventory. if (item.Location == ItemLocation.Inventory) { if (Cube.Any(x => x == item.SnoItem.NameEnglish)) { if (item.SnoItem.CanKanaiCube) { if (!armorySet.HasValue) armorySet = checkArmorySets(item); // CanCanai animation. var cubeTexture = Hud.Texture.KanaiCubeTexture; var h = cubeTexture.Height * 0.6f / 1200.0f * Hud.Window.Size.Height; var rh = h; var mod = armorySet.Value ? 1 : (_stopper.ElapsedMilliseconds % 1000); var ratio = 0.8f + 1.2f / 1000.0f * (mod < 500 ? mod : 1000 - mod); rh *= ratio; var x = rect.Right - h * 0.80f - ((rh - h) / 2); var y = rect.Top - h * 0.20f - ((rh - h) / 2); cubeTexture.Draw(x, y, rh, rh, 1); starChar = null; } } if (item.SnoItem.CanKanaiCube && Hud.Game.Me.IsCubed(item.SnoItem)) { if (items.Where(x => x.Location != ItemLocation.Inventory && x.SnoItem.NameEnglish == item.SnoItem.NameEnglish).Count() == 0) { // This has been cubed and is only in inventory, typically we do not want to save it - blinking. if (!armorySet.HasValue) armorySet = checkArmorySets(item); var mod = armorySet.Value ? 0 : (_stopper.ElapsedMilliseconds % 1500); if (mod < 750) ShowStar(rect, CubeChar, CubeFont, false); starChar = null; } } } if (starChar != null) { bool halfSize = item.Location == ItemLocation.Waist; if (ShowImportantEnabled) { string itemMainStat = GetMainStatName(item); if (Important.Any(x => x.Name == item.SnoItem.NameEnglish && (x.MainStat == itemMainStat || x.MainStat == MAINSTAT_NONE))) { // Important item with our main stat (or wildcard). if (item.Location == ItemLocation.Stash || item.Location == ItemLocation.Inventory) { // Check Follower gear first. if (Follower.Any(x => x == item.SnoItem.NameEnglish)) { ShowStar(rect, FollowerChar, FollowerFont, halfSize); continue; } ShowStar(rect, NoticeChar, NoticeFont, halfSize); continue; } // Show important equipped items with good/bad color. starChar = NoticeChar; if (GetItemKeepDecision(item) == ItemKeepDecision.LooksGood) { ShowStar(rect, starChar, ShowGreenStarEnabled ? LooksGoodFont : NoticeFont, halfSize); } else { ShowStar(rect, starChar, ShowRedStarEnabled ? LooksBadFont : NoticeFont, halfSize); } } } ItemKeepDecision keepDecision = GetItemKeepDecision(item); if (ShowGreenStarEnabled) { if (keepDecision == ItemKeepDecision.LooksGood) ShowStar(rect, starChar, LooksGoodFont, halfSize); } if (ShowRedStarEnabled) { if (keepDecision != ItemKeepDecision.LooksGood) ShowStar(rect, starChar, LooksBadFont, halfSize); } } } } } void ShowStar(System.Drawing.RectangleF rect, string symbol, IFont font, bool halfSize) { // Top right corner. var textLayout = font.GetTextLayout(symbol); font.DrawText(textLayout, rect.Right - rv / 15.0f - textLayout.Metrics.Width, rect.Top - rv / (halfSize ? 8.75f : 17.5f)); } private void DrawItemSocketedLegendaryGemRank(IItem item, System.Drawing.RectangleF rect) { var legendaryGem = item.ItemsInSocket.FirstOrDefault(x => x.Quality == ItemQuality.Legendary && x.JewelRank > -1); if (legendaryGem == null) return; var jewelRank = legendaryGem.JewelRank; if (jewelRank > -1) { var text = jewelRank.ToString("D", CultureInfo.InvariantCulture); var layout = SocketedLegendaryGemRankFont.GetTextLayout(text); SocketedLegendaryGemRankFont.DrawText(layout, rect.X, rect.Y); } } private void DrawItemAncientRank(IItem item, System.Drawing.RectangleF rect) { var ancientRank = item.AncientRank; var caldesannRank = item.CaldesannRank; var font = ancientRank == 1 ? AncientRankFont : PrimalRankFont; string text; if (caldesannRank == 0) { text = ancientRank == 1 ? "A" : "P"; } else { text = caldesannRank.ToString("D", CultureInfo.InvariantCulture); } var textLayout = font.GetTextLayout(text); font.DrawText(textLayout, rect.Right - rv / 15.0f - textLayout.Metrics.Width, rect.Bottom - rv / 35.0f - textLayout.Metrics.Height); } private void DrawItemCanCubed(IItem item, System.Drawing.RectangleF rect) { if ((item.Location != ItemLocation.Inventory) && (item.Location != ItemLocation.Stash)) return; var allowCube = item.SnoItem.CanKanaiCube && !Hud.Game.Me.IsCubed(item.SnoItem); if (allowCube && !item.IsInventoryLocked) { var cubeTexture = Hud.Texture.KanaiCubeTexture; var h = cubeTexture.Height * 0.6f / 1200.0f * Hud.Window.Size.Height; var rh = h; var mod = (_stopper.ElapsedMilliseconds % 1000); var ratio = 0.8f + 1.2f / 1000.0f * (mod < 500 ? mod : 1000 - mod); rh *= ratio; var x = rect.Right - h * 0.80f - ((rh - h) / 2); var y = rect.Top - h * 0.20f - ((rh - h) / 2); cubeTexture.Draw(x, y, rh, rh, 1); } } private void DrawItemHoradricCache(IItem item, System.Drawing.RectangleF rect) { if (!HoradricCacheEnabled) return; if (item.SnoItem.MainGroupCode != "horadriccache") return; var text = ""; if (item.SnoItem.Code.Contains("A1")) text = "A1"; if (item.SnoItem.Code.Contains("A2")) text = "A2"; if (item.SnoItem.Code.Contains("A3")) text = "A3"; if (item.SnoItem.Code.Contains("A4")) text = "A4"; if (item.SnoItem.Code.Contains("A5")) text = "A5"; if (item.SnoItem.Code.Contains("Act1")) text = "A1"; if (item.SnoItem.Code.Contains("Act2")) text = "A2"; if (item.SnoItem.Code.Contains("Act3")) text = "A3"; if (item.SnoItem.Code.Contains("Act4")) text = "A4"; if (item.SnoItem.Code.Contains("Act5")) text = "A5"; if (item.SnoItem.Code.Contains("Hard")) text += ": H"; if (item.SnoItem.Code.Contains("Expert")) text += ": E"; if (item.SnoItem.Code.Contains("Master")) text += ": M"; if (item.SnoItem.Code.Contains("T13")) text += ": T13"; else if (item.SnoItem.Code.Contains("T12")) text += ": T12"; else if (item.SnoItem.Code.Contains("T11")) text += ": T11"; else if (item.SnoItem.Code.Contains("T10")) text += ": T10"; else if (item.SnoItem.Code.Contains("T9")) text += ": T9"; else if (item.SnoItem.Code.Contains("T8")) text += ": T8"; else if (item.SnoItem.Code.Contains("T7")) text += ": T7"; else if (item.SnoItem.Code.Contains("T6")) text += ": T6"; else if (item.SnoItem.Code.Contains("T5")) text += ": T5"; else if (item.SnoItem.Code.Contains("T4")) text += ": T4"; else if (item.SnoItem.Code.Contains("T3")) text += ": T3"; else if (item.SnoItem.Code.Contains("T2")) text += ": T2"; else if (item.SnoItem.Code.Contains("T1")) text += ": T1"; if (item.SnoItem.Code.Contains("Torment13")) text += ": T13"; else if (item.SnoItem.Code.Contains("Torment12")) text += ": T12"; else if (item.SnoItem.Code.Contains("Torment11")) text += ": T11"; else if (item.SnoItem.Code.Contains("Torment10")) text += ": T10"; else if (item.SnoItem.Code.Contains("Torment9")) text += ": T9"; else if (item.SnoItem.Code.Contains("Torment8")) text += ": T8"; else if (item.SnoItem.Code.Contains("Torment7")) text += ": T7"; else if (item.SnoItem.Code.Contains("Torment6")) text += ": T6"; else if (item.SnoItem.Code.Contains("Torment5")) text += ": T5"; else if (item.SnoItem.Code.Contains("Torment4")) text += ": T4"; else if (item.SnoItem.Code.Contains("Torment3")) text += ": T3"; else if (item.SnoItem.Code.Contains("Torment2")) text += ": T2"; else if (item.SnoItem.Code.Contains("Torment1")) text += ": T1"; if (text != null) { var textLayout = HoradricCacheFont.GetTextLayout(text); HoradricCacheFont.DrawText(textLayout, rect.Right - rv / 20.0f - textLayout.Metrics.Width, rect.Bottom - rv / 70.0f - textLayout.Metrics.Height); } } bool checkArmorySets(IItem item) { for (int i = 0; i < Hud.Game.Me.ArmorySets.Length; ++i) { var set = Hud.Game.Me.ArmorySets[i]; if (set.ContainsItem(item)) { return true; } } return false; } public const string MAINSTAT_DEX = "DEX"; public const string MAINSTAT_INT = "INT"; public const string MAINSTAT_STR = "STR"; public const string MAINSTAT_NONE = "---"; public const string NAME_DEX = "Dexterity_Item"; public const string NAME_INT = "Intelligence_Item"; public const string NAME_STR = "Strength_Item"; static string GetMainStatName(IItem item) { if (item != null && item.Perfections != null) { foreach (IItemPerfection perfection in item.Perfections) { string code = perfection.Attribute.Code; if (code == NAME_DEX) return MAINSTAT_DEX; if (code == NAME_INT) return MAINSTAT_INT; if (code == NAME_STR) return MAINSTAT_STR; } } return MAINSTAT_NONE; } public class ImportantItem { public readonly string Name; public readonly string MainStat; public ImportantItem(string name, string mainStat) { Name = name; MainStat = mainStat; } } static ImportantItem important(string name) { return new ImportantItem(name, MAINSTAT_NONE); } static ImportantItem DEX_ITEM(string name) { return new ImportantItem(name, MAINSTAT_DEX); } static ImportantItem INT_ITEM(string name) { return new ImportantItem(name, MAINSTAT_INT); } static ImportantItem STR_ITEM(string name) { return new ImportantItem(name, MAINSTAT_STR); } public static string[] Follower = new string[] { // These important items have "shield" marker in place on star! "Thunderfury, Blessed Blade of the Windseeker", "Eun-jang-do", "Freeze of Deflection", "Defender of Westmarch", "Lidless Wall", "The Ess of Johan", "Overwhelming Desire", "Wyrdward", "Oculus Ring", "Justice Lantern", "Enchanting Favor", }; public static ImportantItem[] Important = new ImportantItem[] { important("Ring of Royal Grandeur"), // Reduces the number of items needed for set bonuses by 1 (to a minimum of 2) important("Unity"), // All damage taken is split between wearers of this item // Barbarian HotA STR_ITEM("Immortal King's Triumph"), STR_ITEM("Immortal King's Eternal Reign"), STR_ITEM("Immortal King's Irons"), STR_ITEM("Immortal King's Tribal Binding"), STR_ITEM("Immortal King's Stature"), STR_ITEM("Immortal King's Stride"), STR_ITEM("Fury of the Ancients"), STR_ITEM("Bracers of the First Men"), STR_ITEM("Magefist"), STR_ITEM("The Traveler's Pledge"), STR_ITEM("The Compass Rose"), STR_ITEM("Convention of Elements"), STR_ITEM("Little Rogue"), STR_ITEM("The Slanderer"), // Follower - Templar // See: https://www.icy-veins.com/d3/follower-skills-and-gearing-patch-2-6-1 STR_ITEM("Thunderfury, Blessed Blade of the Windseeker"), STR_ITEM("Eun-jang-do"), STR_ITEM("Freeze of Deflection"), STR_ITEM("Defender of Westmarch"), STR_ITEM("Lidless Wall"), STR_ITEM("The Ess of Johan"), STR_ITEM("Overwhelming Desire"), STR_ITEM("Wyrdward"), STR_ITEM("Oculus Ring"), STR_ITEM("Justice Lantern"), STR_ITEM("Enchanting Favor"), /* // Speedrun items important("Goldwrap"), // On gold pickup: Gain armor for 5 seconds equal to the amount picked up important("Goldskin"), // +100% Extra Gold, Chance for enemies to drop gold when you hit them important("Custerian Wristguards"), // Picking up gold grants experience important("Gladiator Gauntlets"), // After earning a massacre bonus, gold rains from sky important("Kymbo's Gold"), // +75–100% Extra Gold, Picking up gold heals you for an amount equal to the gold that was picked up // Monk - Inna Exploding Palm DEX_ITEM("Lefebvre's Soliloquy"), DEX_ITEM("Bindings of the Lesser Gods"), DEX_ITEM("Gungdo Gear"), DEX_ITEM("The Crudest Boots"), DEX_ITEM("The Fist of Az'Turrasq"), // Wizard INT_ITEM("Hergbrash's Binding"), INT_ITEM("Ancient Parthan Defenders"), INT_ITEM("Deathwish"), INT_ITEM("Etched Sigil"), */ }; public static string[] Cube = new string[] { "Ring of Royal Grandeur", "Unity", // Barbarian HotA "The Gavel of Judgment", "Magefist", "Aquila Cuirass", "Band of Might", "Unity", /* // Demon Hunter "Aquila Cuirass", // Witch Doctor "The Grin Reaper", "Quetzalcoatl", "Staff of Chiroptera", // Wizard "The Grand Vizier", "Nilfur's Boast", "Halo of Arlyse", */ }; } }