Exemple #1
0
        public override void Render()
        {
            if (!Settings.Enable)
            {
                return;
            }

            ingameUiElements = GameController.Game.IngameState.IngameUi;
            if (ingameUiElements.OpenLeftPanel.IsVisible || ingameUiElements.OpenRightPanel.IsVisible)
            {
                if (ingameUiElements.InventoryPanel.IsVisible)
                {
                    cells = new CellData[CELLS_Y_COUNT, CELLS_X_COUNT];
                    AddItems();
                }
                return;
            }
            RectangleF rect           = GameController.Window.GetWindowRectangle();
            float      xPos           = rect.Width * Settings.PositionX * .01f;
            float      yPos           = rect.Height * Settings.PositionY * .01f;
            var        startDrawPoint = new Vector2(xPos, yPos);

            for (int i = 0; i < cells.GetLength(0); i++)
            {
                for (int j = 0; j < cells.GetLength(1); j++)
                {
                    Vector2 d          = startDrawPoint.Translate(j * Settings.CellSize, i * Settings.CellSize);
                    float   cellWidth  = GetCellSize(cells[i, j].ExtendsX);
                    float   cellHeight = GetCellSize(cells[i, j].ExtendsY);
                    var     rectangleF = new RectangleF(d.X, d.Y, cellWidth, cellHeight);
                    Graphics.DrawImage("cell.png", rectangleF, cells[i, j].Used ? Settings.CellUsedColor : Settings.CellFreeColor);
                }
            }
        }
Exemple #2
0
 public InventoryPreviewPlugin(GameController gameController, Graphics graphics,
                               InventoryPreviewSettings settings)
     : base(gameController, graphics, settings)
 {
     MouseHook.MouseDown += onMouseDown = info => info.Handled = OnMouseEvent(info);
     cells = new CellData[CELLS_Y_COUNT, CELLS_X_COUNT];
 }
        public override void Render()
        {
            if (!holdKey && WinApi.IsKeyDown(Keys.F9))
            {
                holdKey = true;
                Settings.ItemMods.Enable.Value = !Settings.ItemMods.Enable.Value;
                if (!Settings.ItemMods.Enable.Value)
                {
                    SettingsHub.Save(settingsHub);
                }
            }
            else if (holdKey && !WinApi.IsKeyDown(Keys.F9))
            {
                holdKey = false;
            }

            Element uiHover           = GameController.Game.IngameState.UIHover;
            var     inventoryItemIcon = uiHover.AsObject <InventoryItemIcon>();
            Element tooltip           = GetTooltip(inventoryItemIcon);
            Entity  poeEntity         = inventoryItemIcon.Item;

            if (tooltip == null || poeEntity.Address == 0 || !poeEntity.IsValid)
            {
                return;
            }

            RectangleF tooltipRect   = tooltip.GetClientRect();
            var        modsComponent = poeEntity.GetComponent <Mods>();

            if (itemEntity == null || itemEntity.Id != poeEntity.Id)
            {
                List <ItemMod> itemMods = modsComponent.ItemMods;
                mods       = itemMods.Select(item => new ModValue(item, GameController.Files, modsComponent.ItemLevel)).ToList();
                itemEntity = poeEntity;
            }

            if (Settings.ItemLevel.Enable)
            {
                string itemLevel = Convert.ToString(modsComponent.ItemLevel);
                Graphics.DrawText(itemLevel, Settings.ItemLevel.TextSize, tooltipRect.TopLeft.Translate(1, -3), Color.Yellow);
            }

            if (Settings.ItemMods.Enable)
            {
                float bottomTooltip = tooltipRect.Bottom + 5;
                var   modPosition   = new Vector2(tooltipRect.X + 50, bottomTooltip + 4);
                float height        = mods.Aggregate(modPosition, (position, item) => DrawMod(item, position)).Y - bottomTooltip;
                if (height > 4)
                {
                    var modsRect = new RectangleF(tooltipRect.X + 1, bottomTooltip, tooltipRect.Width, height);
                    Graphics.DrawBox(modsRect, Settings.ItemMods.BackgroundColor);
                }
            }

            if (Settings.WeaponDps.Enable && poeEntity.HasComponent <Weapon>())
            {
                DrawWeaponDps(tooltipRect);
            }
        }
Exemple #4
0
 private void DrawPercents(UnitSettings settings, float hpPercent, RectangleF bg)
 {
     if (settings.ShowPercents)
     {
         string text     = Convert.ToString((int)(hpPercent * 100));
         var    position = new Vector2(bg.X + bg.Width + 4, bg.Y);
         Graphics.DrawText(text, settings.TextSize, position, settings.PercentTextColor);
     }
 }
Exemple #5
0
        //public event Action eCheckPluginsDllReload = delegate { };

        public PluginExtensionPlugin(GameController gameController, Graphics graphics)
        {
            BasePlugin.API = this;
            GameController = gameController;
            Graphics       = graphics;
            SearchPlugins();
            InitPlugins();
            gameController.EntityListWrapper.EntityAdded   += OnEntityAdded;
            gameController.EntityListWrapper.EntityRemoved += OnEntityRemoved;
        }
Exemple #6
0
        private async void OnLoad(object sender, EventArgs e)
        {
            Bounds = WinApi.GetClientRectangle(gameHandle);
            WinApi.EnableTransparent(Handle, Bounds);
            graphics = new Graphics2D(this, Bounds.Width, Bounds.Height);
            gameController.Performance = settings.PerformanceSettings;
            plugins.Add(new HealthBarPlugin(gameController, graphics, settings.HealthBarSettings));
            plugins.Add(new MinimapPlugin(gameController, graphics, GatherMapIcons, settings.MapIconsSettings));
            plugins.Add(new LargeMapPlugin(gameController, graphics, GatherMapIcons, settings.MapIconsSettings));
            plugins.Add(new MonsterTracker(gameController, graphics, settings.MonsterTrackerSettings));
            plugins.Add(new PoiTracker(gameController, graphics, settings.PoiTrackerSettings));

            var leftPanel = new PluginPanel(GetLeftCornerMap);

            leftPanel.AddChildren(new XpRatePlugin(gameController, graphics, settings.XpRateSettings, settings));
            leftPanel.AddChildren(new PreloadAlertPlugin(gameController, graphics, settings.PreloadAlertSettings, settings));
            leftPanel.AddChildren(new KillCounterPlugin(gameController, graphics, settings.KillCounterSettings));
            leftPanel.AddChildren(new DpsMeterPlugin(gameController, graphics, settings.DpsMeterSettings));
            leftPanel.AddChildren(new DebugPlugin(gameController, graphics, new DebugPluginSettings(), settings));

            var horizontalPanel = new PluginPanel(Direction.Left);

            leftPanel.AddChildren(horizontalPanel);
            plugins.AddRange(leftPanel.GetPlugins());

            var underPanel = new PluginPanel(GetUnderCornerMap);

            underPanel.AddChildren(new ItemAlertPlugin(gameController, graphics, settings.ItemAlertSettings, settings));
            plugins.AddRange(underPanel.GetPlugins());

            plugins.Add(new AdvancedTooltipPlugin(gameController, graphics, settings.AdvancedTooltipSettings, settings));
            plugins.Add(new MenuPlugin(gameController, graphics, settings));

            await Task.Run(() =>
            {
                plugins.Add(new PluginExtensionPlugin(gameController, graphics)); //Should be after MenuPlugin
            });

            MainMenuWindow.Instance.SelectedPlugin = PluginExtensionPlugin.Plugins.Find(x => x.PluginName == MainMenuWindow.Settings.LastOpenedPlugin);


            Deactivate  += OnDeactivate;
            FormClosing += OnClosing;

            CheckGameWindow();
            CheckGameState();
            graphics.Render       += () => plugins.ForEach(x => x.Render());
            gameController.Clear  += graphics.Clear;
            gameController.Render += graphics.TryRender;
            await Task.Run(() => gameController.WhileLoop());
        }
Exemple #7
0
        private async void OnLoad(object sender, EventArgs e)
        {
            var rect = WinApi.GetClientRectangle(gameHandle);

            Bounds = settings.MenuSettings.AreoMode? rect:new Rectangle(rect.X + rect.Width, rect.Y, 400, rect.Height);
            if (settings.MenuSettings.AreoMode)
            {
                WinApi.EnableTransparent(Handle, Bounds);
            }
            graphics = new Graphics2D(this, Bounds.Width, Bounds.Height);
            if (settings.MenuSettings.AreoMode)
            {
                plugins.Add(new HealthBarPlugin(gameController, graphics, settings.HealthBarSettings));
                plugins.Add(new MinimapPlugin(gameController, graphics, GatherMapIcons, settings.MapIconsSettings));
                plugins.Add(new LargeMapPlugin(gameController, graphics, GatherMapIcons, settings.MapIconsSettings));
            }
            plugins.Add(new MonsterTracker(gameController, graphics, settings.MonsterTrackerSettings));
            plugins.Add(new PoiTracker(gameController, graphics, settings.PoiTrackerSettings));

            var leftPanel = new PluginPanel(GetLeftCornerMap);

            leftPanel.AddChildren(new XpRatePlugin(gameController, graphics, settings.XpRateSettings, settings));
            leftPanel.AddChildren(new PreloadAlertPlugin(gameController, graphics, settings.PreloadAlertSettings, settings));
            leftPanel.AddChildren(new KillCounterPlugin(gameController, graphics, settings.KillCounterSettings));
            leftPanel.AddChildren(new DpsMeterPlugin(gameController, graphics, settings.DpsMeterSettings));

            var horizontalPanel = new PluginPanel(Direction.Left);

            leftPanel.AddChildren(horizontalPanel);
            plugins.AddRange(leftPanel.GetPlugins());

            var underPanel = new PluginPanel(GetUnderCornerMap);

            underPanel.AddChildren(new ItemAlertPlugin(gameController, graphics, settings.ItemAlertSettings, settings));
            plugins.AddRange(underPanel.GetPlugins());

            plugins.Add(new AdvancedTooltipPlugin(gameController, graphics, settings.AdvancedTooltipSettings, settings));
            plugins.Add(new InventoryPreviewPlugin(gameController, graphics, settings.InventoryPreviewSettings));
            plugins.Add(new MenuPlugin(gameController, graphics, settings, this.Handle));

            Deactivate  += OnDeactivate;
            FormClosing += OnClosing;
            if (settings.MenuSettings.AreoMode)
            {
                CheckGameWindow();
            }
            CheckGameState();
            graphics.Render += OnRender;
            await Task.Run(() => graphics.RenderLoop());
        }
Exemple #8
0
        public HealthBarPlugin(GameController gameController, Graphics graphics, HealthBarSettings settings)
            : base(gameController, graphics, settings)
        {
            CreatureType[] types = Enum.GetValues(typeof(CreatureType)).Cast <CreatureType>().ToArray();
            healthBars = new Dictionary <CreatureType, List <HealthBar> >(types.Length);
            foreach (CreatureType type in types)
            {
                healthBars.Add(type, new List <HealthBar>());
            }

            string json = File.ReadAllText("config/debuffPanel.json");

            debuffPanelConfig = JsonConvert.DeserializeObject <DebuffPanelConfig>(json);
        }
Exemple #9
0
 private float DrawDebuff(Func <bool> predicate, float startX, float startY, int index, float marginFix = 0f)
 {
     if (predicate())
     {
         var         size         = Settings.DebuffPanelIconSize;
         const float ICON_COUNT   = 6;
         float       oneIconWidth = 1.0f / ICON_COUNT;
         if (marginFix > 0)
         {
             marginFix = oneIconWidth / marginFix;
         }
         Graphics.DrawImage("debuff_panel.png", new RectangleF(startX, startY, size, size), new RectangleF(index / ICON_COUNT + marginFix, 0, oneIconWidth - marginFix, 1f), Color.White);
         return(size - 1.2f * size * marginFix * ICON_COUNT);
     }
     return(0);
 }
Exemple #10
0
        private float DrawFlatESAmount(HealthBar healthBar, RectangleF bg)
        {
            if (!healthBar.Settings.ShowHealthText || healthBar.Life.MaxES == 0)
            {
                return(bg.Y);
            }

            string curES    = ConvertHelper.ToShorten(healthBar.Life.CurES);
            string maxES    = ConvertHelper.ToShorten(healthBar.Life.MaxES);
            string text     = $"{curES}/{maxES}";
            Color  color    = healthBar.Settings.HealthTextColor;
            var    position = new Vector2(bg.X + bg.Width / 2, bg.Y - 12);
            Size2  size     = Graphics.DrawText(text, healthBar.Settings.TextSize, position, color, FontDrawFlags.Center);

            return((int)bg.Y + (size.Height - bg.Height) / 2 - 10);
        }
        /**
         * I didn't bother to have ES change colour as it gets low, sorry CI
         * players!
         */

        private void DrawFlatESAmount(Life life, UnitSettings settings, RectangleF bg)
        {
            if (!settings.ShowHealthText || life.MaxES == 0)
            {
                return;
            }

            string curES    = ConvertHelper.ToShorten(life.CurES);
            string maxES    = ConvertHelper.ToShorten(life.MaxES);
            string text     = $"{curES}/{maxES}";
            Color  color    = settings.HealthTextColor;
            var    position = new Vector2(bg.X + bg.Width / 2, (bg.Y - 12));

            Graphics.DrawText(text, settings.TextSize, position,
                              color, FontDrawFlags.Center);
        }
Exemple #12
0
        private float DrawFlatLifeAmount(Life life, float hpPercent,
                                         UnitSettings settings, RectangleF bg)
        {
            if (!settings.ShowHealthText)
            {
                return(bg.Y);
            }

            string curHp    = ConvertHelper.ToShorten(life.CurHP);
            string maxHp    = ConvertHelper.ToShorten(life.MaxHP);
            string text     = $"{curHp}/{maxHp}";
            Color  color    = hpPercent <= 0.1f ? settings.HealthTextColorUnder10Percent : settings.HealthTextColor;
            var    position = new Vector2(bg.X + bg.Width / 2, bg.Y);
            Size2  size     = Graphics.DrawText(text, settings.TextSize, position, color, FontDrawFlags.Center);

            return((int)bg.Y + (size.Height - bg.Height) / 2);
        }
Exemple #13
0
        /**
         * I didn't bother to have ES change colour as it gets low, sorry CI
         * players!
         */
        private float DrawFlatESAmount(Life life, UnitSettings settings,
                                       RectangleF bg)
        {
            if (!settings.ShowHealthText || (int)life.MaxES == 0)
            {
                return(bg.Y);
            }

            string curES    = ConvertHelper.ToShorten(life.CurES);
            string maxES    = ConvertHelper.ToShorten(life.MaxES);
            string text     = string.Format("{0}/{1}", curES, maxES);
            Color  color    = settings.HealthTextColor;
            var    position = new Vector2(bg.X + bg.Width / 2, (bg.Y - 12));
            Size2  size     = Graphics.DrawText(text, settings.TextSize, position,
                                                color, FontDrawFlags.Center);

            return((int)bg.Y + (size.Height - bg.Height) / 2);
        }
Exemple #14
0
        private void DrawBackground(Color color, Color outline, RectangleF bg, float hpWidth, float esWidth)
        {
            if (outline != Color.Black)
            {
                Graphics.DrawFrame(bg, 2, outline);
            }
            string healthBar = Settings.ShowIncrements ? "healthbar_increment.png" : "healthbar.png";

            Graphics.DrawImage("healthbar_bg.png", bg, color);
            var hpRectangle = new RectangleF(bg.X, bg.Y, hpWidth, bg.Height);

            Graphics.DrawImage(healthBar, hpRectangle, color, hpWidth * 10 / bg.Width);
            if (Settings.ShowES)
            {
                bg.Width = esWidth;
                Graphics.DrawImage("esbar.png", bg);
            }
        }
Exemple #15
0
        public HealthBarPlugin(GameController gameController, Graphics graphics, HealthBarSettings settings)
            : base(gameController, graphics, settings)
        {
            CreatureType[] types = Enum.GetValues(typeof(CreatureType)).Cast <CreatureType>().ToArray();
            healthBars = new Dictionary <CreatureType, List <HealthBar> >(types.Length);
            foreach (CreatureType type in types)
            {
                healthBars.Add(type, new List <HealthBar>());
            }

            string json = File.ReadAllText("config/debuffPanel.json");

            debuffPanelConfig = JsonConvert.DeserializeObject <DebuffPanelConfig>(json);
            (new Coroutine(() => { foreach (var healthBar in healthBars)
                                   {
                                       healthBar.Value.RemoveAll(hp => !hp.Entity.IsValid);
                                   }
                           }, new WaitRender(10), nameof(HealthBarPlugin), "RemoveAll"))
            .AutoRestart(GameController.CoroutineRunner).Run();
        }
Exemple #16
0
        private void ShowDps(HealthBar healthBar, Vector2 point)
        {
            if (!healthBar.Settings.ShowFloatingCombatDamage)
            {
                return;
            }
            const int MARGIN_TOP           = 2;
            const int LAST_DAMAGE_ADD_SIZE = 7;
            var       fontSize             = healthBar.Settings.FloatingCombatTextSize + LAST_DAMAGE_ADD_SIZE;
            var       textHeight           = Graphics.MeasureText("100500", fontSize).Height;

            healthBar.DpsRefresh();

            point = point.Translate(0, -textHeight - MARGIN_TOP);
            int i = 0;

            foreach (var dps in healthBar.DpsQueue)
            {
                i++;
                var damageColor = healthBar.Settings.FloatingCombatDamageColor;
                var sign        = string.Empty;
                if (dps > 0)
                {
                    damageColor = healthBar.Settings.FloatingCombatHealColor;
                    sign        = "+";
                }

                string dpsText = $"{sign}{dps}";
                Graphics.DrawText(dpsText, fontSize, point, Color.Black, FontDrawFlags.Center);
                point = point.Translate(0, -Graphics.DrawText(dpsText, fontSize,
                                                              point.Translate(1, 0), damageColor, FontDrawFlags.Center).Height - MARGIN_TOP);
                if (i == 1)
                {
                    fontSize -= LAST_DAMAGE_ADD_SIZE;
                }
            }
            healthBar.DpsDequeue();
        }
 public AdvancedTooltipPlugin(GameController gameController, Graphics graphics, AdvancedTooltipSettings settings, SettingsHub settingsHub)
     : base(gameController, graphics, settings)
 {
     this.settingsHub = settingsHub;
 }
Exemple #18
0
        private async void OnLoad(object sender, EventArgs e)
        {
            Bounds = WinApi.GetClientRectangle(gameHandle);
            WinApi.EnableTransparent(Handle, Bounds);
            graphics = new Graphics2D(this, Bounds.Width, Bounds.Height);
            graphics.Render += OnRender;

            plugins.Add(new HealthBarPlugin(gameController, graphics, settings.HealthBarSettings));
            plugins.Add(new MinimapPlugin(gameController, graphics, GatherMapIcons, settings.MapIconsSettings));
            plugins.Add(new LargeMapPlugin(gameController, graphics, GatherMapIcons, settings.MapIconsSettings));
            plugins.Add(new MonsterTracker(gameController, graphics, settings.MonsterTrackerSettings));
            plugins.Add(new PoiTracker(gameController, graphics, settings.PoiTrackerSettings));

            var leftPanel = new PluginPanel(GetLeftCornerMap);
            leftPanel.AddChildren(new XpRatePlugin(gameController, graphics, settings.XpRateSettings));
            leftPanel.AddChildren(new PreloadAlertPlugin(gameController, graphics, settings.PreloadAlertSettings));
            var horizontalPanel = new PluginPanel(Direction.Left);
            horizontalPanel.AddChildren(new DpsMeterPlugin(gameController, graphics, settings.DpsMeterSettings));
            horizontalPanel.AddChildren(new KillsCounterPlugin(gameController, graphics, settings.KillsCounterSettings));
            //horizontalPanel.AddChildren(new ItemCounterPlugin(gameController, graphics, settings.ItemCounterSettings)); // Doesnt work yet
            leftPanel.AddChildren(horizontalPanel);
            plugins.AddRange(leftPanel.GetPlugins());

            var underPanel = new PluginPanel(GetUnderCornerMap);
            underPanel.AddChildren(new ItemAlertPlugin(gameController, graphics, settings.ItemAlertSettings));
            plugins.AddRange(underPanel.GetPlugins());

            plugins.Add(new AdvancedTooltipPlugin(gameController, graphics, settings.AdvancedTooltipSettings, settings));
            plugins.Add(new InventoryPreviewPlugin(gameController, graphics, settings.InventoryPreviewSettings));
            plugins.Add(new MenuPlugin(gameController, graphics, settings));

            Deactivate += OnDeactivate;
            FormClosing += OnClosing;

            CheckGameWindow();
            CheckGameState();
            await Task.Run(() => graphics.RenderLoop());
        }
        public override void Render()
        {
            try
            {
                if (!holdKey && WinApi.IsKeyDown(Keys.F9))
                {
                    holdKey = true;
                    Settings.ItemMods.Enable.Value = !Settings.ItemMods.Enable.Value;
                    if (!Settings.ItemMods.Enable.Value)
                    {
                        SettingsHub.Save(settingsHub);
                    }
                }
                else if (holdKey && !WinApi.IsKeyDown(Keys.F9))
                {
                    holdKey = false;
                }
                Element uiHover           = GameController.Game.IngameState.UIHover;
                var     inventoryItemIcon = uiHover.AsObject <HoverItemIcon>();

                Element tooltip   = inventoryItemIcon.Tooltip;
                Entity  poeEntity = inventoryItemIcon.Item;

                if (tooltip == null || poeEntity.Address == 0 || !poeEntity.IsValid)
                {
                    return;
                }
                RectangleF tooltipRect = tooltip.GetClientRect();



                var  modsComponent = poeEntity.GetComponent <Mods>();
                long id            = 0;
                if (inventoryItemIcon.ToolTipType == ToolTipType.InventoryItem)
                {
                    id = poeEntity.InventoryId;
                }
                else
                {
                    id = poeEntity.Id;
                }

                if (itemEntity == null || itemEntity.Id != id)
                {
                    List <ItemMod> itemMods = modsComponent.ItemMods;
                    mods = itemMods.Select(item => new ModValue(item, GameController.Files, modsComponent.ItemLevel,
                                                                GameController.Files.BaseItemTypes.Translate(poeEntity.Path))).ToList();
                    itemEntity = poeEntity;
                }

                int t1 = 0;
                foreach (string tier in from item in mods where item.CouldHaveTiers() && item.Tier == 1 select " \u2605 ")
                {
                    Graphics.DrawText(tier, 18, tooltipRect.TopLeft.Translate(0 + 14 * t1++, 56), Settings.ItemMods.T1Color);
                }

                int t2 = 0;
                foreach (string tier in from item in mods where item.CouldHaveTiers() && item.Tier == 2 select " \u2605 ")
                {
                    Graphics.DrawText(tier, 18, tooltipRect.TopLeft.Translate(t1 * 14 + 14 * t2++, 56), Settings.ItemMods.T2Color);
                }

                if (Settings.ItemLevel.Enable)
                {
                    string itemLevel = Convert.ToString(modsComponent.ItemLevel);
                    var    imageSize = Settings.ItemLevel.TextSize + 10;
                    Graphics.DrawText(itemLevel, Settings.ItemLevel.TextSize, tooltipRect.TopLeft.Translate(2, 2), Settings.ItemLevel.TextColor);
                    Graphics.DrawImage("menu-colors.png", new RectangleF(tooltipRect.TopLeft.X - 2, tooltipRect.TopLeft.Y - 2, imageSize, imageSize), Settings.ItemLevel.BackgroundColor);
                }

                if (Settings.ItemMods.Enable)
                {
                    float bottomTooltip = tooltipRect.Bottom + 5;
                    var   modPosition   = new Vector2(tooltipRect.X + 50, bottomTooltip + 4);
                    float height        = mods.Aggregate(modPosition, (position, item) => DrawMod(item, position)).Y - bottomTooltip;
                    if (height > 4)
                    {
                        var modsRect = new RectangleF(tooltipRect.X + 1, bottomTooltip, tooltipRect.Width, height);
                        Graphics.DrawBox(modsRect, Settings.ItemMods.BackgroundColor);
                    }
                }

                if (Settings.WeaponDps.Enable && poeEntity.HasComponent <Weapon>())
                {
                    DrawWeaponDps(tooltipRect);
                }
            }
            catch
            { }
        }
        private Vector2 DrawMod(ModValue item, Vector2 position)
        {
            const float EPSILON = 0.001f;
            const int   MARGIN_BOTTOM = 4, MARGIN_LEFT = 50;

            Vector2          oldPosition = position;
            ItemModsSettings settings    = Settings.ItemMods;

            string affix = item.AffixType == ModsDat.ModType.Prefix ? "[P]"
                : item.AffixType == ModsDat.ModType.Suffix ? "[S]" : "[?]";

            Dictionary <int, Color> TColors = new Dictionary <int, Color>
            {
                { 1, settings.T1Color },
                { 2, settings.T2Color },
                { 3, settings.T3Color }
            };

            if (item.AffixType != ModsDat.ModType.Hidden)
            {
                if (item.CouldHaveTiers())
                {
                    affix += $" T{item.Tier} ";
                }

                if (item.AffixType == ModsDat.ModType.Prefix)
                {
                    Graphics.DrawText(affix, settings.ModTextSize, position.Translate(5 - MARGIN_LEFT, 0), settings.PrefixColor);
                    if (!TColors.TryGetValue(item.Tier, out TColor))
                    {
                        TColor = settings.PrefixColor;
                    }
                }

                if (item.AffixType == ModsDat.ModType.Suffix)
                {
                    Graphics.DrawText(affix, settings.ModTextSize, position.Translate(5 - MARGIN_LEFT, 0), settings.SuffixColor);
                    if (!TColors.TryGetValue(item.Tier, out TColor))
                    {
                        TColor = settings.SuffixColor;
                    }
                }
                Size2 textSize = Graphics.DrawText(item.AffixText, settings.ModTextSize, position, TColor);
                if (textSize != new Size2())
                {
                    position.Y += textSize.Height;
                }
            }

            for (int i = 0; i < 4; i++)
            {
                IntRange range = item.Record.StatRange[i];
                if (range.Min == 0 && range.Max == 0)
                {
                    continue;
                }

                StatsDat.StatRecord stat = item.Record.StatNames[i];
                int value = item.StatValue[i];
                if (value <= -1000 || stat == null)
                {
                    continue;
                }
                float  percents = range.GetPercentage(value);
                bool   noSpread = !range.HasSpread();
                double hue      = percents > 1 ? 180 : 120 * percents;
                if (noSpread)
                {
                    hue = 300;
                }

                string line2 = string.Format(noSpread ? "{0}" : "{0} [{1}]", stat, range);
                Graphics.DrawText(line2, settings.ModTextSize, position, Color.Gainsboro);

                string  statText     = stat.ValueToString(value);
                Vector2 statPosition = position.Translate(-5, 0);
                Color   statColor    = ColorUtils.ColorFromHsv(hue, 1, 1);
                Size2   txSize       = Graphics.DrawText(statText, settings.ModTextSize, statPosition, Color.Gainsboro, FontDrawFlags.Right);
                position.Y += txSize.Height;
            }
            return(Math.Abs(position.Y - oldPosition.Y) > EPSILON?position.Translate(0, MARGIN_BOTTOM) : oldPosition);
        }
        private void DrawWeaponDps(RectangleF clientRect)
        {
            var   weapon            = itemEntity.GetComponent <Weapon>();
            float aSpd              = (float)Math.Round(1000f / weapon.AttackTime, 2);
            int   cntDamages        = Enum.GetValues(typeof(DamageType)).Length;
            var   doubleDpsPerStat  = new float[cntDamages];
            float physDmgMultiplier = 1;
            int   PhysHi            = weapon.DamageMax;
            int   PhysLo            = weapon.DamageMin;

            foreach (ModValue mod in mods)
            {
                for (int iStat = 0; iStat < 4; iStat++)
                {
                    IntRange range = mod.Record.StatRange[iStat];
                    if (range.Min == 0 && range.Max == 0)
                    {
                        continue;
                    }

                    StatsDat.StatRecord theStat = mod.Record.StatNames[iStat];
                    int value = mod.StatValue[iStat];
                    switch (theStat.Key)
                    {
                    case "physical_damage_+%":
                    case "local_physical_damage_+%":
                        physDmgMultiplier += value / 100f;
                        break;

                    case "local_attack_speed_+%":
                        aSpd *= (100f + value) / 100;
                        break;

                    case "local_minimum_added_physical_damage":
                        PhysLo += value;
                        break;

                    case "local_maximum_added_physical_damage":
                        PhysHi += value;
                        break;

                    case "local_minimum_added_fire_damage":
                    case "local_maximum_added_fire_damage":
                    case "unique_local_minimum_added_fire_damage_when_in_main_hand":
                    case "unique_local_maximum_added_fire_damage_when_in_main_hand":
                        doubleDpsPerStat[(int)DamageType.Fire] += value;
                        break;

                    case "local_minimum_added_cold_damage":
                    case "local_maximum_added_cold_damage":
                    case "unique_local_minimum_added_cold_damage_when_in_off_hand":
                    case "unique_local_maximum_added_cold_damage_when_in_off_hand":
                        doubleDpsPerStat[(int)DamageType.Cold] += value;
                        break;

                    case "local_minimum_added_lightning_damage":
                    case "local_maximum_added_lightning_damage":
                        doubleDpsPerStat[(int)DamageType.Lightning] += value;
                        break;

                    case "unique_local_minimum_added_chaos_damage_when_in_off_hand":
                    case "unique_local_maximum_added_chaos_damage_when_in_off_hand":
                    case "local_minimum_added_chaos_damage":
                    case "local_maximum_added_chaos_damage":
                        doubleDpsPerStat[(int)DamageType.Chaos] += value;
                        break;
                    }
                }
            }
            WeaponDpsSettings settings = Settings.WeaponDps;

            Color[] elementalDmgColors = { Color.White,
                                           settings.DmgFireColor,
                                           settings.DmgColdColor,
                                           settings.DmgLightningColor,
                                           settings.DmgChaosColor };
            physDmgMultiplier += itemEntity.GetComponent <Quality>().ItemQuality / 100f;
            PhysLo             = (int)Math.Round(PhysLo * physDmgMultiplier);
            PhysHi             = (int)Math.Round(PhysHi * physDmgMultiplier);
            doubleDpsPerStat[(int)DamageType.Physical] = PhysLo + PhysHi;

            aSpd = (float)Math.Round(aSpd, 2);
            float pDps     = doubleDpsPerStat[(int)DamageType.Physical] / 2 * aSpd;
            float eDps     = 0;
            int   firstEmg = 0;
            Color DpsColor = settings.pDamageColor;

            for (int i = 1; i < cntDamages; i++)
            {
                eDps += doubleDpsPerStat[i] / 2 * aSpd;
                if (doubleDpsPerStat[i] > 0)
                {
                    if (firstEmg == 0)
                    {
                        firstEmg = i;
                        DpsColor = elementalDmgColors[i];
                    }
                    else
                    {
                        DpsColor = settings.eDamageColor;
                    }
                }
            }

            var   textPosition = new Vector2(clientRect.Right - 2, clientRect.Y + 1);
            Size2 pDpsSize     = pDps > 0
                ? Graphics.DrawText(pDps.ToString("#.#") + " pDps", settings.DpsTextSize, textPosition, FontDrawFlags.Right)
                : new Size2();
            Size2 eDpsSize = eDps > 0
                ? Graphics.DrawText(eDps.ToString("#.#") + " eDps", settings.DpsTextSize,
                                    textPosition.Translate(0, pDpsSize.Height), DpsColor, FontDrawFlags.Right)
                : new Size2();

            var   dps     = pDps + eDps;
            Size2 dpsSize = dps > 0
              ? Graphics.DrawText(dps.ToString("#.#") + " Dps", settings.DpsTextSize,
                                  textPosition.Translate(0, pDpsSize.Height + eDpsSize.Height), Color.White, FontDrawFlags.Right)
              : new Size2();
            Vector2 dpsTextPosition = textPosition.Translate(0, pDpsSize.Height + eDpsSize.Height + dpsSize.Height);

            Graphics.DrawText("dps", settings.DpsNameTextSize, dpsTextPosition, settings.TextColor, FontDrawFlags.Right);
            Graphics.DrawImage("preload-end.png", new RectangleF(textPosition.X - 86, textPosition.Y - 6, 90, 65), settings.BackgroundColor);
        }
        private void DrawWeaponDps(RectangleF clientRect)
        {
            var   weapon            = itemEntity.GetComponent <Weapon>();
            float aSpd              = 1000f / weapon.AttackTime;
            int   cntDamages        = Enum.GetValues(typeof(DamageType)).Length;
            var   doubleDpsPerStat  = new float[cntDamages];
            float physDmgMultiplier = 1;

            doubleDpsPerStat[(int)DamageType.Physical] = weapon.DamageMax + weapon.DamageMin;
            foreach (ModValue mod in mods)
            {
                for (int iStat = 0; iStat < 4; iStat++)
                {
                    IntRange range = mod.Record.StatRange[iStat];
                    if (range.Min == 0 && range.Max == 0)
                    {
                        continue;
                    }

                    StatsDat.StatRecord theStat = mod.Record.StatNames[iStat];
                    int value = mod.StatValue[iStat];
                    switch (theStat.Key)
                    {
                    case "physical_damage_+%":
                    case "local_physical_damage_+%":
                        physDmgMultiplier += value / 100f;
                        break;

                    case "local_attack_speed_+%":
                        aSpd *= (100f + value) / 100;
                        break;

                    case "local_minimum_added_physical_damage":
                    case "local_maximum_added_physical_damage":
                        doubleDpsPerStat[(int)DamageType.Physical] += value;
                        break;

                    case "local_minimum_added_fire_damage":
                    case "local_maximum_added_fire_damage":
                    case "unique_local_minimum_added_fire_damage_when_in_main_hand":
                    case "unique_local_maximum_added_fire_damage_when_in_main_hand":
                        doubleDpsPerStat[(int)DamageType.Fire] += value;
                        break;

                    case "local_minimum_added_cold_damage":
                    case "local_maximum_added_cold_damage":
                    case "unique_local_minimum_added_cold_damage_when_in_off_hand":
                    case "unique_local_maximum_added_cold_damage_when_in_off_hand":
                        doubleDpsPerStat[(int)DamageType.Cold] += value;
                        break;

                    case "local_minimum_added_lightning_damage":
                    case "local_maximum_added_lightning_damage":
                        doubleDpsPerStat[(int)DamageType.Lightning] += value;
                        break;

                    case "unique_local_minimum_added_chaos_damage_when_in_off_hand":
                    case "unique_local_maximum_added_chaos_damage_when_in_off_hand":
                    case "local_minimum_added_chaos_damage":
                    case "local_maximum_added_chaos_damage":
                        doubleDpsPerStat[(int)DamageType.Chaos] += value;
                        break;
                    }
                }
            }

            doubleDpsPerStat[(int)DamageType.Physical] *= physDmgMultiplier;
            int quality = itemEntity.GetComponent <Quality>().ItemQuality;

            if (quality > 0)
            {
                doubleDpsPerStat[(int)DamageType.Physical] += (weapon.DamageMax + weapon.DamageMin) * quality / 100f;
            }

            float pDps      = doubleDpsPerStat[(int)DamageType.Physical] / 2 * aSpd;
            float eDps      = 0;
            int   firstEmg  = 0;
            Color eDpsColor = Color.White;

            for (int i = 1; i < cntDamages; i++)
            {
                eDps += doubleDpsPerStat[i] / 2 * aSpd;
                if (doubleDpsPerStat[i] > 0)
                {
                    if (firstEmg == 0)
                    {
                        firstEmg  = i;
                        eDpsColor = elementalDmgColors[i];
                    }
                    else
                    {
                        eDpsColor = Color.DarkViolet;
                    }
                }
            }

            WeaponDpsSettings settings = Settings.WeaponDps;
            var   textPosition         = new Vector2(clientRect.Right - 2, clientRect.Y + 1);
            Size2 pDpsSize             = pDps > 0
                ? Graphics.DrawText(pDps.ToString("#.#"), settings.DpsTextSize, textPosition, FontDrawFlags.Right)
                : new Size2();
            Size2 eDpsSize = eDps > 0
                ? Graphics.DrawText(eDps.ToString("#.#"), settings.DpsTextSize,
                                    textPosition.Translate(0, pDpsSize.Height), eDpsColor, FontDrawFlags.Right)
                : new Size2();
            Vector2 dpsTextPosition = textPosition.Translate(0, pDpsSize.Height + eDpsSize.Height);

            Graphics.DrawText("dps", settings.DpsNameTextSize, dpsTextPosition, settings.TextColor, FontDrawFlags.Right);
        }