Example #1
0
        private void Display_RenderedWorld(object sender, StardewModdingAPI.Events.RenderedWorldEventArgs e)
        {
            if (Game1.activeClickableMenu == null && PlacedAugmentorsManager.Instance != null)
            {
                GameLocation CurrentLocation = Game1.player.currentLocation;

                bool IsHoveringPlacedObject = CurrentLocation.Objects.TryGetValue(HoveredTile, out Object HoveredObject);
                if (IsHoveringPlacedObject)
                {
                    Dictionary <AugmentorType, int> AttachedAugmentors = PlacedAugmentorsManager.Instance.GetAugmentorQuantities(CurrentLocation.NameOrUniqueName, HoveredTile);
                    bool HasAttachedAugmentors = AttachedAugmentors.Any(x => x.Value > 0);
                    if (MachineInfo.TryGetMachineInfo(HoveredObject, out MachineInfo MI))
                    {
                        SpriteFont DefaultFont = Game1.dialogueFont;

                        //  Draw a tooltip showing what effects the held item will have when attached to this machine
                        if (Game1.player.CurrentItem is Augmentor HeldAugmentor && HeldAugmentor.IsAugmentable(HoveredObject))
                        {
                            AttachedAugmentors.TryGetValue(HeldAugmentor.AugmentorType, out int CurrentAttachedQuantity);

                            double CurrentEffect = CurrentAttachedQuantity <= 0 ?
                                                   Augmentor.GetDefaultEffect(HeldAugmentor.AugmentorType) : Augmentor.ComputeEffect(HeldAugmentor.AugmentorType, CurrentAttachedQuantity, MI.RequiresInput);
                            double NewEffectSingle = Augmentor.ComputeEffect(HeldAugmentor.AugmentorType, CurrentAttachedQuantity + 1, MI.RequiresInput);
                            double NewEffectAll    = Augmentor.ComputeEffect(HeldAugmentor.AugmentorType, CurrentAttachedQuantity + HeldAugmentor.Stack, MI.RequiresInput);

                            //  Example of desired tooltip:
                            //        -------------------------------------------
                            //        |          [Icon] Time to process:        |
                            //        |-----------------------------------------|
                            //        |  Current Effect: 95.5%                  |
                            //        |      New Effect: 92.2% (1) / 81.1% (4)  |
                            //        -------------------------------------------

                            int   Padding         = 28;
                            int   MarginAfterIcon = 10;
                            float LabelTextScale  = 0.75f;
                            float ValueTextScale  = 1.0f;

                            //  Compute sizes of each row so we know how big the tooltip is, and can horizontally center the header and other rows

                            //  Compute size of header
                            int HeaderHorizontalPadding = 4;
                            Augmentor.TryGetIconDetails(HeldAugmentor.AugmentorType, out Texture2D IconTexture, out Rectangle IconSourcePosition, out float IconScale, out SpriteEffects IconEffects);
                            Vector2 IconSize        = new Vector2(IconSourcePosition.Width * IconScale, IconSourcePosition.Height * IconScale);
                            string  HeaderText      = string.Format("{0}:", HeldAugmentor.GetEffectDescription());
                            Vector2 HeaderTextSize  = DefaultFont.MeasureString(HeaderText) * LabelTextScale;
                            float   HeaderRowWidth  = IconSize.X + MarginAfterIcon + HeaderTextSize.X + HeaderHorizontalPadding * 2;
                            float   HeaderRowHeight = Math.Max(IconSize.Y, HeaderTextSize.Y);

                            //  Compute size of horizontal separator
                            int HorizontalSeparatorHeight = 6;
                            int HorizontalSeparatorMargin = 8;

                            //  Compute size of the labels before the effect values
                            int     MarginAfterLabel       = 8;
                            string  CurrentEffectLabel     = string.Format("{0}:", Translate("CurrentEffectLabel"));
                            Vector2 CurrentEffectLabelSize = DefaultFont.MeasureString(CurrentEffectLabel) * LabelTextScale;
                            string  NewEffectLabel         = string.Format("{0}:", Translate("NewEffectLabel"));
                            Vector2 NewEffectLabelSize     = DefaultFont.MeasureString(NewEffectLabel) * LabelTextScale;
                            float   EffectLabelWidth       = Math.Max(CurrentEffectLabelSize.X, NewEffectLabelSize.X);
                            Vector2 EffectLabelSize        = new Vector2(EffectLabelWidth, CurrentEffectLabelSize.Y + NewEffectLabelSize.Y);

                            //  Compute size of the effect values
                            string  CurrentEffectValue     = string.Format("{0}% ({1})", (CurrentEffect * 100.0).ToString("0.##"), CurrentAttachedQuantity);
                            Vector2 CurrentEffectValueSize = DrawHelpers.MeasureStringWithSpecialNumbers(CurrentEffectValue, ValueTextScale, 0.0f);
                            string  NewEffectValue;
                            if (HeldAugmentor.Stack > 1)
                            {
                                NewEffectValue = string.Format("{0}% ({1}) / {2}% ({3})",
                                                               (NewEffectSingle * 100.0).ToString("0.##"), (CurrentAttachedQuantity + 1), (NewEffectAll * 100.0).ToString("0.##"), (CurrentAttachedQuantity + HeldAugmentor.Stack));
                            }
                            else
                            {
                                NewEffectValue = string.Format("{0}% ({1})", (NewEffectSingle * 100.0).ToString("0.##"), (CurrentAttachedQuantity + 1));
                            }
                            Vector2 NewEffectValueSize = DrawHelpers.MeasureStringWithSpecialNumbers(NewEffectValue, ValueTextScale, 0.0f);

                            Vector2 EffectContentSize = new Vector2(EffectLabelWidth + MarginAfterLabel + Math.Max(CurrentEffectValueSize.X, NewEffectValueSize.X),
                                                                    Math.Max(CurrentEffectLabelSize.Y, CurrentEffectValueSize.Y) + Math.Max(NewEffectLabelSize.Y, NewEffectValueSize.Y));

                            //  Compute total size of tooltip, draw the background
                            Vector2 ToolTipSize    = new Vector2(Padding * 2 + Math.Max(HeaderRowWidth, EffectContentSize.X), Padding + HeaderRowHeight + HorizontalSeparatorMargin + HorizontalSeparatorHeight + HorizontalSeparatorMargin + EffectContentSize.Y + Padding);
                            Point   ToolTipTopleft = DrawHelpers.GetTopleftPosition(new Point((int)ToolTipSize.X, (int)ToolTipSize.Y), MouseScreenPosition, 100);
                            DrawHelpers.DrawBox(e.SpriteBatch, new Rectangle(ToolTipTopleft.X, ToolTipTopleft.Y, (int)ToolTipSize.X, (int)ToolTipSize.Y));
                            float CurrentY = ToolTipTopleft.Y + Padding;

                            //  Draw the header
                            float   HeaderStartX = ToolTipTopleft.X + (ToolTipSize.X - HeaderRowWidth) / 2.0f;
                            Vector2 IconPosition = new Vector2(HeaderStartX, CurrentY + (HeaderRowHeight - IconSize.Y) / 2.0f);
                            e.SpriteBatch.Draw(IconTexture, IconPosition, IconSourcePosition, Color.White, 0f, Vector2.Zero, IconScale, IconEffects, 1f);
                            Vector2 HeaderTextPosition = new Vector2(HeaderStartX + IconSize.X + MarginAfterIcon, CurrentY + (HeaderRowHeight - HeaderTextSize.Y) / 2.0f);
                            e.SpriteBatch.DrawString(DefaultFont, HeaderText, HeaderTextPosition, Color.Black, 0.0f, Vector2.Zero, LabelTextScale, SpriteEffects.None, 1.0f);
                            CurrentY += HeaderRowHeight + HorizontalSeparatorMargin;

                            //  Draw the horizontal separator
                            DrawHelpers.DrawHorizontalSeparator(e.SpriteBatch, ToolTipTopleft.X + Padding, (int)CurrentY, (int)(ToolTipSize.X - 2 * Padding), HorizontalSeparatorHeight);
                            CurrentY += HorizontalSeparatorHeight + HorizontalSeparatorMargin;

                            //  Draw the current effect
                            Vector2 CurrentEffectLabelPosition = new Vector2(ToolTipTopleft.X + Padding + (EffectLabelWidth - CurrentEffectLabelSize.X), CurrentY);
                            Vector2 CurrentEffectValuePosition = new Vector2(ToolTipTopleft.X + Padding + EffectLabelWidth + MarginAfterLabel, CurrentY);
                            e.SpriteBatch.DrawString(DefaultFont, CurrentEffectLabel, CurrentEffectLabelPosition, Color.Black, 0.0f, Vector2.Zero, LabelTextScale, SpriteEffects.None, 1.0f);
                            DrawHelpers.DrawStringWithSpecialNumbers(e.SpriteBatch, CurrentEffectValuePosition, CurrentEffectValue, ValueTextScale, Color.White);
                            CurrentY += Math.Max(CurrentEffectLabelSize.Y, CurrentEffectValueSize.Y);

                            //  Draw the new effect
                            Vector2 NewEffectLabelPosition = new Vector2(ToolTipTopleft.X + Padding + (EffectLabelWidth - NewEffectLabelSize.X), CurrentY);
                            Vector2 NewEffectValuePosition = new Vector2(ToolTipTopleft.X + Padding + EffectLabelWidth + MarginAfterLabel, CurrentY);
                            e.SpriteBatch.DrawString(DefaultFont, NewEffectLabel, NewEffectLabelPosition, Color.Black, 0.0f, Vector2.Zero, LabelTextScale, SpriteEffects.None, 1.0f);
                            DrawHelpers.DrawStringWithSpecialNumbers(e.SpriteBatch, NewEffectValuePosition, NewEffectValue, ValueTextScale, Color.White);
                        }
                        //  Draw a tooltip showing what effects are currently applied to this machine
                        else if (HasAttachedAugmentors)
                        {
                            int Padding         = 28;
                            int MarginAfterIcon = 10;

                            //  Compute the size of each icon
                            Dictionary <AugmentorType, Vector2> IconSizes = new Dictionary <AugmentorType, Vector2>();
                            foreach (KeyValuePair <AugmentorType, int> KVP in AttachedAugmentors.Where(x => x.Value > 0))
                            {
                                Augmentor.TryGetIconDetails(KVP.Key, out Texture2D IconTexture, out Rectangle IconSourcePosition, out float IconScale, out SpriteEffects IconEffects);
                                Vector2 IconSize = new Vector2(IconSourcePosition.Width * IconScale, IconSourcePosition.Height * IconScale);
                                IconSizes.Add(KVP.Key, IconSize);
                            }
                            float IconColumnWidth = IconSizes.Values.Max(x => x.Y);

                            //  Compute the size of each row (each row shows the effect of a type of augmentor that has been applied to this machine)
                            Dictionary <AugmentorType, Vector2> RowSizes = new Dictionary <AugmentorType, Vector2>();
                            foreach (KeyValuePair <AugmentorType, int> KVP in AttachedAugmentors.Where(x => x.Value > 0))
                            {
                                double  CurrentEffect = Augmentor.ComputeEffect(KVP.Key, KVP.Value, MI.RequiresInput);
                                string  Text          = string.Format("{0}% ({1})", (CurrentEffect * 100.0).ToString("0.#"), KVP.Value);
                                Vector2 TextSize      = DrawHelpers.MeasureStringWithSpecialNumbers(Text, 1.0f, 4.0f);

                                float RowWidth  = IconColumnWidth + MarginAfterIcon + TextSize.X;
                                float RowHeight = Math.Max(IconSizes[KVP.Key].Y, TextSize.Y);
                                RowSizes.Add(KVP.Key, new Vector2(RowWidth, RowHeight));
                            }

                            //  Compute total size of tooltip, draw the background
                            Vector2 ToolTipSize    = new Vector2(Padding * 2 + RowSizes.Values.Max(x => x.X), Padding * 2 + RowSizes.Values.Sum(x => x.Y));
                            Point   ToolTipTopleft = DrawHelpers.GetTopleftPosition(new Point((int)ToolTipSize.X, (int)ToolTipSize.Y), MouseScreenPosition, 100);
                            DrawHelpers.DrawBox(e.SpriteBatch, new Rectangle(ToolTipTopleft.X, ToolTipTopleft.Y, (int)ToolTipSize.X, (int)ToolTipSize.Y));
                            float CurrentY = ToolTipTopleft.Y + Padding;

                            //  Draw each row
                            float RowStartX = ToolTipTopleft.X + Padding;
                            foreach (KeyValuePair <AugmentorType, int> KVP in AttachedAugmentors.Where(x => x.Value > 0))
                            {
                                float CurrentX  = RowStartX;
                                float RowHeight = RowSizes[KVP.Key].Y;

                                //  Draw the icon
                                Augmentor.TryGetIconDetails(KVP.Key, out Texture2D IconTexture, out Rectangle IconSourcePosition, out float IconScale, out SpriteEffects IconEffects);
                                Vector2 IconSize     = IconSizes[KVP.Key];
                                Vector2 IconPosition = new Vector2(CurrentX + (IconColumnWidth - IconSize.X) / 2.0f, CurrentY + (RowHeight - IconSize.Y) / 2.0f);
                                e.SpriteBatch.Draw(IconTexture, IconPosition, IconSourcePosition, Color.White, 0f, Vector2.Zero, IconScale, IconEffects, 1f);
                                CurrentX += IconColumnWidth + MarginAfterIcon;

                                //  Draw the value
                                double  CurrentEffect = Augmentor.ComputeEffect(KVP.Key, KVP.Value, MI.RequiresInput);
                                string  Text          = string.Format("{0}% ({1})", (CurrentEffect * 100.0).ToString("0.#"), KVP.Value);
                                Vector2 TextSize      = DrawHelpers.MeasureStringWithSpecialNumbers(Text, 1.0f, 0.0f);
                                Vector2 TextPosition  = new Vector2(CurrentX, CurrentY + (RowHeight - TextSize.Y) / 2.0f);
                                DrawHelpers.DrawStringWithSpecialNumbers(e.SpriteBatch, TextPosition, Text, 1.0f, Color.White);

                                CurrentY += RowHeight;
                            }

                            //Maybe also show MinutesUntilReady if it's not ReadyForHarvest?
                        }
                    }
                }
            }
Example #2
0
        private void Display_RenderedWorld(object sender, RenderedWorldEventArgs e)
        {
            if (Game1.activeClickableMenu == null)
            {
                GameLocation CurrentLocation = Game1.player.currentLocation;

                bool IsHoveringPlacedObject = CurrentLocation.Objects.TryGetValue(HoveredTile, out SObject HoveredObject);
                if (IsHoveringPlacedObject)
                {
                    if (UserConfig.DrawToolTip)
                    {
                        //  Draw a tooltip that shows how many of the machine were combined, and its total combined processing power
                        //  Such as: "Quantity: 5\nPower: 465%"
                        if (HoveredObject.TryGetCombinedQuantity(out int CombinedQuantity))
                        {
                            float UIScaleFactor = Game1.options.zoomLevel / Game1.options.uiScale;

                            SpriteFont DefaultFont          = Game1.dialogueFont;
                            int        Padding              = 25;
                            int        MarginBetweenColumns = 10;
                            int        MarginBetweenRows    = 5;
                            float      LabelTextScale       = 0.75f;
                            float      ValueTextScale       = 1.0f;

                            List <string> RowHeaders = new List <string>()
                            {
                                Helper.Translation.Get("ToolTipQuantityLabel"), Helper.Translation.Get("ToolTipPowerLabel")
                            };
                            List <Vector2> RowHeaderSizes = RowHeaders.Select(x => DefaultFont.MeasureString(x) * LabelTextScale).ToList();

                            double        ProcessingPower          = UserConfig.ComputeProcessingPower(CombinedQuantity) * 100.0;
                            string        FormattedProcessingPower = string.Format("{0}%", ProcessingPower.ToString("#.#"));
                            List <string> RowValues = new List <string>()
                            {
                                CombinedQuantity.ToString(), FormattedProcessingPower
                            };
                            List <Vector2> RowValueSizes = RowValues.Select(x => DrawHelpers.MeasureStringWithSpecialNumbers(x, ValueTextScale, 0.0f)).ToList();

                            //  Measure the tooltip
                            List <int> RowHeights = new List <int>();
                            for (int i = 0; i < RowHeaders.Count; i++)
                            {
                                RowHeights.Add((int)Math.Max(RowHeaderSizes[i].Y, RowValueSizes[i].Y));
                            }

                            List <int> ColumnWidths = new List <int> {
                                (int)RowHeaderSizes.Max(x => x.X),
                                (int)RowValueSizes.Max(x => x.X)
                            };

                            int   ToolTipTopWidth = Padding + ColumnWidths.Sum() + (ColumnWidths.Count - 1) * MarginBetweenColumns + Padding;
                            int   ToolTipHeight   = Padding + RowHeights.Sum() + (RowHeights.Count - 1) * MarginBetweenRows + Padding;
                            Point ToolTipTopleft  = DrawHelpers.GetTopleftPosition(new Point(ToolTipTopWidth, ToolTipHeight),
                                                                                   new Point((int)((MouseScreenPosition.X + UserConfig.ToolTipOffset.X) / UIScaleFactor), (int)((MouseScreenPosition.Y + UserConfig.ToolTipOffset.Y) / UIScaleFactor)), 100);

                            //  Draw tooltip background
                            DrawHelpers.DrawBox(e.SpriteBatch, new Rectangle(ToolTipTopleft.X, ToolTipTopleft.Y, ToolTipTopWidth, ToolTipHeight));

                            //  Draw each row's header and value
                            int CurrentY = ToolTipTopleft.Y + Padding;
                            for (int i = 0; i < RowHeights.Count; i++)
                            {
                                int CurrentRowHeight = RowHeights[i];

                                //  Draw the row header
                                Vector2 RowHeaderPosition = new Vector2(
                                    ToolTipTopleft.X + Padding + ColumnWidths[0] - RowHeaderSizes[i].X,
                                    CurrentY + (RowHeights[i] - RowHeaderSizes[i].Y) / 2.0f
                                    );
                                e.SpriteBatch.DrawString(DefaultFont, RowHeaders[i], RowHeaderPosition, Color.Black, 0.0f, Vector2.Zero, LabelTextScale, SpriteEffects.None, 1.0f);

                                //  Draw the row value
                                Vector2 RowValuePosition = new Vector2(
                                    ToolTipTopleft.X + Padding + ColumnWidths[0] + MarginBetweenColumns,
                                    CurrentY + (RowHeights[i] - RowValueSizes[i].Y) / 2.0f
                                    );
                                DrawHelpers.DrawStringWithSpecialNumbers(e.SpriteBatch, RowValuePosition, RowValues[i], ValueTextScale, Color.White);

                                CurrentY += CurrentRowHeight + MarginBetweenRows;
                            }
                        }
                    }
                }
            }
        }
Example #3
0
        private void Display_RenderedWorld(object sender, RenderedWorldEventArgs e)
        {
            if (Game1.activeClickableMenu == null)
            {
                GameLocation CurrentLocation = Game1.player.currentLocation;

                bool IsHoveringPlacedObject = CurrentLocation.Objects.TryGetValue(HoveredTile, out SObject HoveredObject);
                if (IsHoveringPlacedObject)
                {
                    if (UserConfig.DrawToolTip)
                    {
                        //  Draw a tooltip that shows how many of the machine were combined, and its total combined processing power
                        //  Such as: "Quantity: 5\nPower: 465%"
                        if (HoveredObject.TryGetCombinedQuantity(out int CombinedQuantity))
                        {
                            Cask    Cask        = HoveredObject as Cask;
                            bool    IsCask      = Cask != null;
                            CrabPot CrabPot     = HoveredObject as CrabPot;
                            bool    IsCrabPot   = CrabPot != null;
                            bool    IsScarecrow = HoveredObject.IsScarecrow();

                            bool HasHeldObject = HoveredObject.heldObject?.Value != null;

                            float UIScaleFactor = Game1.options.zoomLevel / Game1.options.uiScale;

                            SpriteFont DefaultFont          = Game1.dialogueFont;
                            int        Padding              = 25;
                            int        MarginBetweenColumns = 10;
                            int        MarginBetweenRows    = 5;
                            float      LabelTextScale       = 0.75f;
                            float      ValueTextScale       = 1.0f;

                            bool ShowDurationInfo = UserConfig.ToolTipShowDuration && UserConfig.ShouldModifyProcessingSpeed(HoveredObject);
                            bool ShowQuantityInfo = UserConfig.ToolTipShowQuantity && UserConfig.ShouldModifyInputsAndOutputs(HoveredObject);

                            //  Compute row headers
                            List <string> RowHeaders = new List <string>()
                            {
                                Helper.Translation.Get("ToolTipQuantityLabel"), Helper.Translation.Get("ToolTipPowerLabel")
                            };
                            if (ShowDurationInfo)
                            {
                                if (IsCask)
                                {
                                    //RowHeaders.Add(Helper.Translation.Get("ToolTipCaskAgingRateLabel"));
                                    if (HasHeldObject)
                                    {
                                        RowHeaders.Add(Helper.Translation.Get("ToolTipCaskDaysUntilIridiumLabel"));
                                    }
                                }
                                else if (IsCrabPot)
                                {
                                    RowHeaders.Add(Helper.Translation.Get("ToolTipCrabPotProcessingIntervalLabel"));
                                }
                                else
                                {
                                    if (HasHeldObject)
                                    {
                                        RowHeaders.Add(Helper.Translation.Get("ToolTipMinutesRemainingLabel"));
                                    }
                                }
                            }
                            if (ShowQuantityInfo)
                            {
                                if (HasHeldObject && HoveredObject.HasModifiedOutput())
                                {
                                    RowHeaders.Add(Helper.Translation.Get("ToolTipProducedQuantityLabel"));
                                }
                            }
                            if (IsScarecrow)
                            {
                                RowHeaders.Add(Helper.Translation.Get("ToolTipScarecrowRadiusLabel"));
                            }
                            List <Vector2> RowHeaderSizes = RowHeaders.Select(x => DefaultFont.MeasureString(x) * LabelTextScale).ToList();

                            double ProcessingPower          = UserConfig.ComputeProcessingPower(CombinedQuantity) * 100.0;
                            string FormattedProcessingPower = string.Format("{0}%", ProcessingPower.ToString("0.#"));

                            //  Compute row values
                            List <string> RowValues = new List <string>()
                            {
                                CombinedQuantity.ToString(), FormattedProcessingPower
                            };
                            if (ShowDurationInfo)
                            {
                                if (IsCask)
                                {
                                    //RowValues.Add(Cask.agingRate.Value.ToString("0.##"));
                                    if (HasHeldObject)
                                    {
                                        RowValues.Add(Math.Ceiling(Cask.daysToMature.Value / Cask.agingRate.Value).ToString("0.##"));
                                    }
                                }
                                else if (IsCrabPot)
                                {
                                    CrabPot.TryGetProcessingInterval(out double Power, out double IntervalHours, out int IntervalMinutes);
                                    RowValues.Add(IntervalMinutes.ToString());
                                }
                                else
                                {
                                    if (HasHeldObject)
                                    {
                                        RowValues.Add(HoveredObject.MinutesUntilReady.ToString("0.##"));
                                    }
                                }
                            }
                            if (ShowQuantityInfo)
                            {
                                if (HasHeldObject && HoveredObject.HasModifiedOutput())
                                {
                                    RowValues.Add(HoveredObject.heldObject.Value.Stack.ToString());
                                }
                            }
                            if (IsScarecrow)
                            {
                                //  Subtract 1 because the game internally counts the scarecrow's occupied tile as part of its radius, but users usually would be confused by that
                                //  So a typical user expects radius=8 for a regular scarecrow, even though the game does its calculations with radius=9
                                int OriginalRadius = HoveredObject.GetScarecrowBaseRadius() - 1;
                                int AlteredRadius  = HoveredObject.GetScarecrowRadius() - 1;
                                //RowValues.Add(string.Format("{0}-->{1}", OriginalRadius, AlteredRadius));
                                RowValues.Add(AlteredRadius.ToString());
                            }
                            List <Vector2> RowValueSizes = RowValues.Select(x => DrawHelpers.MeasureStringWithSpecialNumbers(x, ValueTextScale, 0.0f)).ToList();

                            //  Measure the tooltip
                            List <int> RowHeights = new List <int>();
                            for (int i = 0; i < RowHeaders.Count; i++)
                            {
                                RowHeights.Add((int)Math.Max(RowHeaderSizes[i].Y, RowValueSizes[i].Y));
                            }

                            List <int> ColumnWidths = new List <int> {
                                (int)RowHeaderSizes.Max(x => x.X),
                                (int)RowValueSizes.Max(x => x.X)
                            };

                            int   ToolTipTopWidth = Padding + ColumnWidths.Sum() + (ColumnWidths.Count - 1) * MarginBetweenColumns + Padding;
                            int   ToolTipHeight   = Padding + RowHeights.Sum() + (RowHeights.Count - 1) * MarginBetweenRows + Padding;
                            Point ToolTipTopleft  = DrawHelpers.GetTopleftPosition(new Point(ToolTipTopWidth, ToolTipHeight),
                                                                                   new Point((int)((MouseScreenPosition.X + UserConfig.ToolTipOffset.X) / UIScaleFactor), (int)((MouseScreenPosition.Y + UserConfig.ToolTipOffset.Y) / UIScaleFactor)), 100);

                            //  Draw tooltip background
                            DrawHelpers.DrawBox(e.SpriteBatch, new Rectangle(ToolTipTopleft.X, ToolTipTopleft.Y, ToolTipTopWidth, ToolTipHeight));

                            //  Draw each row's header and value
                            int CurrentY = ToolTipTopleft.Y + Padding;
                            for (int i = 0; i < RowHeights.Count; i++)
                            {
                                int CurrentRowHeight = RowHeights[i];

                                //  Draw the row header
                                Vector2 RowHeaderPosition = new Vector2(
                                    ToolTipTopleft.X + Padding + ColumnWidths[0] - RowHeaderSizes[i].X,
                                    CurrentY + (RowHeights[i] - RowHeaderSizes[i].Y) / 2.0f
                                    );
                                e.SpriteBatch.DrawString(DefaultFont, RowHeaders[i], RowHeaderPosition, Color.Black, 0.0f, Vector2.Zero, LabelTextScale, SpriteEffects.None, 1.0f);

                                //  Draw the row value
                                Vector2 RowValuePosition = new Vector2(
                                    ToolTipTopleft.X + Padding + ColumnWidths[0] + MarginBetweenColumns,
                                    CurrentY + (RowHeights[i] - RowValueSizes[i].Y) / 2.0f
                                    );
                                DrawHelpers.DrawStringWithSpecialNumbers(e.SpriteBatch, RowValuePosition, RowValues[i], ValueTextScale, Color.White);

                                CurrentY += CurrentRowHeight + MarginBetweenRows;
                            }
                        }
                    }
                }
            }
        }