Esempio n. 1
0
        protected override void LoadSettings(BagInstance Data)
        {
            if (Data != null)
            {
                this.Size     = Data.Size;
                this.Autofill = Data.Autofill;

                this.BaseName         = ItemBagsMod.Translate("BundleBagName");
                this.DescriptionAlias = ItemBagsMod.Translate("BundleBagDescription");

                Contents.Clear();
                foreach (BagItem Item in Data.Contents)
                {
                    this.Contents.Add(Item.ToObject());
                }

                if (Data.IsCustomIcon)
                {
                    this.CustomIconSourceTexture   = BagType.SourceTexture.SpringObjects;
                    this.CustomIconTexturePosition = Data.OverriddenIcon;
                }
                else
                {
                    ResetIcon();
                }
            }
        }
Esempio n. 2
0
        /// <param name="Autofill">If true, then when the player picks up an item that can be stored in this bag, it will automatically be stored if there is space for it.</param>
        public BoundedBag(BagType TypeInfo, ContainerSize Size, bool Autofill)
            : base(BagType.GetTranslatedName(TypeInfo), "", Size, TypeInfo.GetIconTexture(), TypeInfo.IconSourceRect, new Vector2(16, 16), 0.5f, 1f)
        {
            this.TypeInfo = TypeInfo;
            this.SizeInfo = TypeInfo.SizeSettings.FirstOrDefault(x => x.Size == Size);
            if (SizeInfo == null) // This should never happen but just in case...
            {
                SizeInfo = TypeInfo.SizeSettings.First();
            }
            this.Autofill = Autofill;

            _MaxStackSize = ItemBagsMod.UserConfig.GetStandardBagCapacity(Size, TypeInfo);

            DescriptionAlias = string.Format("{0}\n({1})",
                                             BagType.GetTranslatedDescription(TypeInfo),
                                             ItemBagsMod.Translate("CapacityDescription", new Dictionary <string, string>()
            {
                { "count", MaxStackSize.ToString() }
            }));

            if (SizeInfo.Size != Size)
            {
                this.AllowedObjects = new ReadOnlyCollection <AllowedObject>(new List <AllowedObject>());
            }
            else
            {
                this.AllowedObjects = new ReadOnlyCollection <AllowedObject>(SizeInfo.Items.Select(x => new AllowedObject(x)).ToList());
            }
            this.ExcludedAutofillItems = new Dictionary <string, HashSet <ObjectQuality> >();
        }
Esempio n. 3
0
 /// <summary>Default parameterless constructor intended for use by XML Serialization. Do not use this constructor to instantiate a bag.</summary>
 public BoundedBag()
     : base(ItemBagsMod.Translate("DefaultBagName"), ItemBagsMod.Translate("DefaultBagDescription"), ContainerSize.Small, null, null, new Vector2(16, 16), 0.5f, 1f)
 {
     this.TypeInfo = ItemBagsMod.BagConfig.BagTypes.First();
     this.Autofill = false;
     this.ExcludedAutofillItems = new Dictionary <string, HashSet <ObjectQuality> >();
 }
Esempio n. 4
0
        /// <param name="Size">Must be a Size within <see cref="ValidSizes"/></param>
        public BundleBag(ContainerSize Size, bool Autofill)
            : base(ItemBagsMod.Translate("BundleBagName"), ItemBagsMod.Translate("BundleBagDescription"), Size, true)
        {
            if (!ValidSizes.Contains(Size))
            {
                throw new InvalidOperationException(string.Format("Size '{0}' is not valid for BundleBag types", Size.ToString()));
            }

            this.Autofill = Autofill;
        }
Esempio n. 5
0
        /// <summary>Default parameterless constructor intended for use by XML Serialization. Do not use this constructor to instantiate a bag.</summary>
        public BoundedBag()
            : base(ItemBagsMod.Translate("DefaultBagName"), ItemBagsMod.Translate("DefaultBagDescription"), ContainerSize.Small, null, null, new Vector2(16, 16), 0.5f, 1f)
        {
            this.TypeInfo = ItemBagsMod.BagConfig.BagTypes.First();
            this.SizeInfo = TypeInfo.SizeSettings.FirstOrDefault(x => x.Size == ContainerSize.Small);
            this.Autofill = false;

            _MaxStackSize              = ItemBagsMod.UserConfig.GetStandardBagCapacity(Size, TypeInfo);
            this.AllowedObjects        = new List <AllowedObject>().AsReadOnly();
            this.ExcludedAutofillItems = new Dictionary <string, HashSet <ObjectQuality> >();
        }
Esempio n. 6
0
        public void DrawToolTips(SpriteBatch b)
        {
            //  Draw tooltips on the hovered item inside the bag
            if (HoveredSlot.HasValue)
            {
                Object HoveredItem = GetHoveredItem();
                if (HoveredItem != null)
                {
                    Rectangle Location;
                    if (IsNavigatingWithGamepad)
                    {
                        Location = HoveredSlot.Value; //new Rectangle(HoveredSlot.Value.Right, HoveredSlot.Value.Bottom, 1, 1);
                    }
                    else
                    {
                        Location = new Rectangle(Game1.getMouseX() - 8, Game1.getMouseY() + 36, 8 + 36, 1);
                    }
                    DrawHelpers.DrawToolTipInfo(b, Location, HoveredItem, true, true, true, true, true, true, Bag.MaxStackSize);
                }
            }

            //  Draw tooltips on the sidebar buttons
            if (IsRightSidebarVisible && HoveredContentsButton.HasValue)
            {
                string ButtonToolTip = "";
                if (HoveredContentsButton.Value == ContentsSidebarButton.SortingProperty)
                {
                    ButtonToolTip = ItemBagsMod.Translate(string.Format("RucksackSortProperty{0}ToolTip", Rucksack.SortProperty.ToString()));
                }
                else if (HoveredContentsButton.Value == ContentsSidebarButton.SortingOrder)
                {
                    if (Rucksack.SortOrder == SortingOrder.Ascending)
                    {
                        ButtonToolTip = ItemBagsMod.Translate("RucksackSortOrderAscendingToolTip");
                    }
                    else if (Rucksack.SortOrder == SortingOrder.Descending)
                    {
                        ButtonToolTip = ItemBagsMod.Translate("RucksackSortOrderDescendingToolTip");
                    }
                }

                if (!string.IsNullOrEmpty(ButtonToolTip))
                {
                    int     Margin      = 16;
                    Vector2 ToolTipSize = Game1.smallFont.MeasureString(ButtonToolTip);
                    DrawHelpers.DrawBox(b, HoveredContentsButtonBounds.Value.Left - (int)(ToolTipSize.X + Margin * 2), HoveredContentsButtonBounds.Value.Top, (int)(ToolTipSize.X + Margin * 2), (int)(ToolTipSize.Y + Margin * 2));
                    b.DrawString(Game1.smallFont, ButtonToolTip, new Vector2(HoveredContentsButtonBounds.Value.Left - Margin - ToolTipSize.X, HoveredContentsButtonBounds.Value.Top + Margin), Color.Black);
                }
            }
        }
Esempio n. 7
0
        protected override void LoadSettings(BagInstance Data)
        {
            if (Data != null)
            {
                this.Size = Data.Size;

                string SizeName = ItemBagsMod.Translate(string.Format("Size{0}Name", Size.GetDescription()));
                DescriptionAlias = string.Format("{0}\n({1})\n({2})",
                                                 ItemBagsMod.Translate("OmniBagDescription"),
                                                 ItemBagsMod.Translate("CapacityDescription", new Dictionary <string, string>()
                {
                    { "count", MaxStackSize.ToString() }
                }),
                                                 ItemBagsMod.Translate("OmniBagCapacityDescription", new Dictionary <string, string>()
                {
                    { "size", SizeName }
                })
                                                 );

                this.NestedBags.Clear();
                foreach (BagInstance NestedInstance in Data.NestedBags)
                {
                    if (NestedInstance.TryDecode(out ItemBag NestedBag))
                    {
                        this.NestedBags.Add(NestedBag);
                    }
                }

                Contents.Clear();
                foreach (BagItem Item in Data.Contents)
                {
                    this.Contents.Add(Item.ToObject());
                }

                if (Data.IsCustomIcon)
                {
                    this.CustomIconSourceTexture   = BagType.SourceTexture.SpringObjects;
                    this.CustomIconTexturePosition = Data.OverriddenIcon;
                }
                else
                {
                    ResetIcon();
                }
            }
        }
Esempio n. 8
0
        public static string GetTranslatedName(BagType Type)
        {
            string TranslationKey = string.Format("{0}Name", Type.Name.Replace(" ", ""));

            try
            {
                string Translated = ItemBagsMod.Translate(TranslationKey);
                if (!string.IsNullOrEmpty(Translated))
                {
                    return(Translated);
                }
                else
                {
                    return(Type.Name);
                }
            }
            catch (Exception) { return(Type.Name); }
        }
Esempio n. 9
0
        /// <summary>Default parameterless constructor intended for use by XML Serialization. Do not use this constructor to instantiate a bag.</summary>
        public OmniBag() : base(ItemBagsMod.Translate("OmniBagName"), ItemBagsMod.Translate("OmniBagDescription"), ContainerSize.Small, null, null, new Vector2(16, 16), 0.5f, 1f)
        {
            string SizeName = ItemBagsMod.Translate(string.Format("Size{0}Name", Size.GetDescription()));

            DescriptionAlias = string.Format("{0}\n({1})\n({2})",
                                             ItemBagsMod.Translate("OmniBagDescription"),
                                             ItemBagsMod.Translate("CapacityDescription", new Dictionary <string, string>()
            {
                { "count", MaxStackSize.ToString() }
            }),
                                             ItemBagsMod.Translate("OmniBagCapacityDescription", new Dictionary <string, string>()
            {
                { "size", SizeName }
            })
                                             );

            this.NestedBags = new List <ItemBag>();

            LoadTextures();
        }
Esempio n. 10
0
        protected override void LoadSettings(BagInstance Data)
        {
            if (Data != null)
            {
                this.Size     = Data.Size;
                this.Autofill = Data.Autofill;
                this.ExcludedAutofillItems = new Dictionary <string, HashSet <ObjectQuality> >();
                foreach (var KVP in Data.ExcludedAutofillItems)
                {
                    this.ExcludedAutofillItems.Add(KVP.Key, KVP.Value);
                }

                //  Load the type
                this.TypeInfo = ItemBagsMod.BagConfig.BagTypes.FirstOrDefault(x => x.Id == Data.TypeId);
                if (TypeInfo == null)
                {
                    string Warning = string.Format("Warning - no BagType with Id = {0} was found. Did you manually edit your {1} json file or delete a .json file from 'Modded Bags' folder? The saved bag cannot be properly loaded without a corresponding type!"
                                                   + " To prevent crashes, this bag will be automatically converted to a default BagType.", Data.TypeId, ItemBagsMod.BagConfigDataKey);
                    ItemBagsMod.ModInstance.Monitor.Log(Warning, LogLevel.Warn);

                    //  To prevent crashes, convert this bag into a different bag type that exists
                    this.TypeInfo = ItemBagsMod.BagConfig.GetDefaultBoundedBagType();
                }

                //  Load the size configuration
                this.SizeInfo = TypeInfo.SizeSettings.FirstOrDefault(x => x.Size == Size);
                if (SizeInfo == null)
                {
                    string Warning = string.Format("Warning - BagType with Id = {0} does not contain any settings for Size={1}. Did you manually edit your {2} json file?"
                                                   + " The saved bag cannot be properly loaded without the corresponding settings for this size! To prevent crashes, this bag will be automatically converted to a default size for this BagType.",
                                                   this.TypeInfo.Id, this.Size.ToString(), ItemBagsMod.BagConfigDataKey);
                    ItemBagsMod.ModInstance.Monitor.Log(Warning, LogLevel.Warn);

                    this.SizeInfo = TypeInfo.SizeSettings.First();
                }

                _MaxStackSize = ItemBagsMod.UserConfig.GetStandardBagCapacity(Size, TypeInfo);

                this.BaseName    = BagType.GetTranslatedName(TypeInfo);
                DescriptionAlias = string.Format("{0}\n({1})",
                                                 BagType.GetTranslatedDescription(TypeInfo),
                                                 ItemBagsMod.Translate("CapacityDescription", new Dictionary <string, string>()
                {
                    { "count", MaxStackSize.ToString() }
                }));

                if (SizeInfo.Size != Size)
                {
                    this.AllowedObjects = new ReadOnlyCollection <AllowedObject>(new List <AllowedObject>());
                }
                else
                {
                    this.AllowedObjects = new ReadOnlyCollection <AllowedObject>(SizeInfo.Items.Select(x => new AllowedObject(x)).ToList());
                }

                this.Contents.Clear();
                foreach (BagItem Item in Data.Contents)
                {
                    this.Contents.Add(Item.ToObject());
                }

                if (Data.IsCustomIcon)
                {
                    this.Icon = Game1.objectSpriteSheet;
                    this.IconTexturePosition = Data.OverriddenIcon;
                }
                else
                {
                    ResetIcon();
                }
            }
        }
Esempio n. 11
0
        public sealed override void draw(SpriteBatch b)
        {
            try
            {
                DrawBox(b, xPositionOnScreen, yPositionOnScreen, width, height);
                int SeparatorHeight = 24;
                DrawHorizontalSeparator(b, xPositionOnScreen, InventoryMenu.TopLeftScreenPosition.Y - InventoryMargin - SeparatorHeight / 2, width, SeparatorHeight);
                InventoryMenu.Draw(b);

                if (IsLeftSidebarVisible || IsRightSidebarVisible)
                {
                    if (IsLeftSidebarVisible)
                    {
                        //  Draw the deposit/withdraw-all buttons
                        Rectangle ArrowUpIconSourceRect   = new Rectangle(421, 459, 12, 12);
                        Rectangle ArrowDownIconSourceRect = new Rectangle(421, 472, 12, 12);
                        int       ArrowSize = (int)(ArrowUpIconSourceRect.Width * 1.5 / 32.0 * DepositAllBounds.Width);
                        b.Draw(Game1.menuTexture, DepositAllBounds, new Rectangle(128, 128, 64, 64), Color.White);
                        b.Draw(Game1.mouseCursors, new Rectangle(DepositAllBounds.X + (DepositAllBounds.Width - ArrowSize) / 2, DepositAllBounds.Y + (DepositAllBounds.Height - ArrowSize) / 2, ArrowSize, ArrowSize), ArrowUpIconSourceRect, Color.White);
                        b.Draw(Game1.menuTexture, WithdrawAllBounds, new Rectangle(128, 128, 64, 64), Color.White);
                        b.Draw(Game1.mouseCursors, new Rectangle(WithdrawAllBounds.X + (WithdrawAllBounds.Width - ArrowSize) / 2, WithdrawAllBounds.Y + (WithdrawAllBounds.Height - ArrowSize) / 2, ArrowSize, ArrowSize), ArrowDownIconSourceRect, Color.White);

                        //  Draw the autofill togglebutton
                        Rectangle HandIconSourceRect = new Rectangle(32, 0, 10, 10);
                        int       HandIconSize       = (int)(HandIconSourceRect.Width * 2.0 / 32.0 * AutolootBounds.Width);
                        b.Draw(Game1.menuTexture, AutolootBounds, new Rectangle(128, 128, 64, 64), Color.White);
                        b.Draw(Game1.mouseCursors, new Rectangle(AutolootBounds.X + (AutolootBounds.Width - HandIconSize) / 2, AutolootBounds.Y + (AutolootBounds.Height - HandIconSize) / 2, HandIconSize, HandIconSize), HandIconSourceRect, Color.White);

                        if (Bag is BoundedBag BB)
                        {
                            if (!BB.Autofill)
                            {
                                Rectangle DisabledIconSourceRect = new Rectangle(322, 498, 12, 12);
                                int       DisabledIconSize       = (int)(DisabledIconSourceRect.Width * 1.5 / 32.0 * AutolootBounds.Width);
                                Rectangle Destination            = new Rectangle(AutolootBounds.Right - DisabledIconSize - 2, AutolootBounds.Bottom - DisabledIconSize - 2, DisabledIconSize, DisabledIconSize);
                                b.Draw(Game1.mouseCursors, Destination, DisabledIconSourceRect, Color.White);
                            }
                        }
                        else if (Bag is Rucksack RS)
                        {
                            if (!RS.Autofill)
                            {
                                Rectangle DisabledIconSourceRect = new Rectangle(322, 498, 12, 12);
                                int       DisabledIconSize       = (int)(DisabledIconSourceRect.Width * 1.5 / 32.0 * AutolootBounds.Width);
                                Rectangle Destination            = new Rectangle(AutolootBounds.Right - DisabledIconSize - 2, AutolootBounds.Bottom - DisabledIconSize - 2, DisabledIconSize, DisabledIconSize);
                                b.Draw(Game1.mouseCursors, Destination, DisabledIconSourceRect, Color.White);
                            }
                            else
                            {
                                if (RS.AutofillPriority == AutofillPriority.Low)
                                {
                                    Rectangle LowPriorityIconSourceRect = new Rectangle(421, 472, 12, 12);
                                    int       LowPriorityIconSize       = (int)(LowPriorityIconSourceRect.Width * 1.0 / 32.0 * AutolootBounds.Width);
                                    Rectangle Destination = new Rectangle(AutolootBounds.Right - LowPriorityIconSize - 2, AutolootBounds.Bottom - LowPriorityIconSize - 2, LowPriorityIconSize, LowPriorityIconSize);
                                    b.Draw(Game1.mouseCursors, Destination, LowPriorityIconSourceRect, Color.White);
                                }
                                else if (RS.AutofillPriority == AutofillPriority.High)
                                {
                                    Rectangle HighPriorityIconSourceRect = new Rectangle(421, 459, 12, 12);
                                    int       HighPriorityIconSize       = (int)(HighPriorityIconSourceRect.Width * 1.0 / 32.0 * AutolootBounds.Width);
                                    Rectangle Destination = new Rectangle(AutolootBounds.Right - HighPriorityIconSize - 2, AutolootBounds.Bottom - HighPriorityIconSize - 2, HighPriorityIconSize, HighPriorityIconSize);
                                    b.Draw(Game1.mouseCursors, Destination, HighPriorityIconSourceRect, Color.White);
                                }
                            }
                        }
                    }

                    if (IsRightSidebarVisible)
                    {
                        //  Draw the help button
                        Rectangle HelpIconSourceRect = new Rectangle(176, 425, 9, 12);
                        int       HelpIconWidth      = (int)(HelpIconSourceRect.Width * 1.5 / 32.0 * HelpInfoBounds.Width);
                        int       HelpIconHeight     = (int)(HelpIconSourceRect.Height * 1.5 / 32.0 * HelpInfoBounds.Height);
                        b.Draw(Game1.menuTexture, HelpInfoBounds, new Rectangle(128, 128, 64, 64), Color.White);
                        b.Draw(Game1.mouseCursors, new Rectangle(HelpInfoBounds.X + (HelpInfoBounds.Width - HelpIconWidth) / 2, HelpInfoBounds.Y + (HelpInfoBounds.Height - HelpIconHeight) / 2, HelpIconWidth, HelpIconHeight), HelpIconSourceRect, Color.White);

                        if (Bag.CanCustomizeIcon())
                        {
                            //  Draw the customize icon button
                            Rectangle CustomizeSourceRect = new Rectangle(121, 471, 12, 12);
                            int       CustomizeIconWidth  = CustomizeIconBounds.Width;
                            int       CustomizeIconHeight = CustomizeIconBounds.Height;
                            b.Draw(Game1.mouseCursors, new Rectangle(CustomizeIconBounds.X + (CustomizeIconBounds.Width - CustomizeIconWidth) / 2, CustomizeIconBounds.Y + (CustomizeIconBounds.Height - CustomizeIconHeight) / 2,
                                                                     CustomizeIconWidth, CustomizeIconHeight), CustomizeSourceRect, Color.White);
                            b.Draw(Game1.menuTexture, CustomizeIconBounds, new Rectangle(128, 128, 64, 64), Color.White);
                        }
                    }

                    //  Draw a yellow border around the hovered sidebar button
                    if (HoveredButton.HasValue)
                    {
                        Rectangle HoveredBounds  = HoveredButtonBounds.Value;
                        Color     HighlightColor = Color.Yellow;
                        Texture2D Highlight      = TextureHelpers.GetSolidColorTexture(Game1.graphics.GraphicsDevice, HighlightColor);
                        b.Draw(Highlight, HoveredBounds, Color.White * 0.25f);
                        int BorderThickness = HoveredBounds.Width / 16;
                        DrawBorder(b, HoveredBounds, BorderThickness, HighlightColor);
                    }
                }

                Content.Draw(b);

                if (IsShowingModalMenu && CustomizeIconMenu != null)
                {
                    CustomizeIconMenu.Draw(b);
                }
                else
                {
                    InventoryMenu.DrawToolTips(b);
                    Content.DrawToolTips(b);

                    //  Draw tooltips on the sidebar buttons
                    if ((IsLeftSidebarVisible || IsRightSidebarVisible) && HoveredButton.HasValue)
                    {
                        if (IsLeftSidebarVisible)
                        {
                            string ButtonToolTip = "";
                            if (HoveredButton.Value == SidebarButton.DepositAll)
                            {
                                ButtonToolTip = ItemBagsMod.Translate("DepositAllToolTip");
                            }
                            else if (HoveredButton.Value == SidebarButton.WithdrawAll)
                            {
                                ButtonToolTip = ItemBagsMod.Translate("WithdrawAllToolTip");
                            }
                            else if (HoveredButton.Value == SidebarButton.Autoloot)
                            {
                                if (Bag is BoundedBag BB)
                                {
                                    ButtonToolTip = ItemBagsMod.Translate(BB.Autofill ? "AutofillOnToolTip" : "AutofillOffToolTip");
                                }
                                else if (Bag is Rucksack RS)
                                {
                                    string TranslationKey;
                                    if (RS.Autofill)
                                    {
                                        if (RS.AutofillPriority == AutofillPriority.Low)
                                        {
                                            TranslationKey = "RucksackAutofillLowPriorityToolTip";
                                        }
                                        else if (RS.AutofillPriority == AutofillPriority.High)
                                        {
                                            TranslationKey = "RucksackAutofillHighPriorityToolTip";
                                        }
                                        else
                                        {
                                            throw new NotImplementedException(string.Format("Unrecognized Rucksack AutofillPriority: {0}", RS.AutofillPriority.ToString()));
                                        }
                                    }
                                    else
                                    {
                                        TranslationKey = "RucksackAutofillOffToolTip";
                                    }
                                    ButtonToolTip = ItemBagsMod.Translate(TranslationKey);
                                }
                            }

                            if (!string.IsNullOrEmpty(ButtonToolTip))
                            {
                                int     Margin      = 16;
                                Vector2 ToolTipSize = Game1.smallFont.MeasureString(ButtonToolTip);
                                DrawBox(b, HoveredButtonBounds.Value.Right, HoveredButtonBounds.Value.Top, (int)(ToolTipSize.X + Margin * 2), (int)(ToolTipSize.Y + Margin * 2));
                                b.DrawString(Game1.smallFont, ButtonToolTip, new Vector2(HoveredButtonBounds.Value.Right + Margin, HoveredButtonBounds.Value.Top + Margin), Color.Black);
                            }
                        }

                        if (IsRightSidebarVisible)
                        {
                            string ButtonToolTip = "";
                            if (HoveredButton.Value == SidebarButton.HelpInfo)
                            {
                                ButtonToolTip = ItemBagsMod.Translate("HelpInfoToolTip");
                            }
                            else if (HoveredButton.Value == SidebarButton.CustomizeIcon)
                            {
                                ButtonToolTip = ItemBagsMod.Translate("CustomizeIconToolTip");
                            }

                            if (!string.IsNullOrEmpty(ButtonToolTip))
                            {
                                int     Margin      = 16;
                                Vector2 ToolTipSize = Game1.smallFont.MeasureString(ButtonToolTip);
                                DrawBox(b, HoveredButtonBounds.Value.Left - (int)(ToolTipSize.X + Margin * 2), HoveredButtonBounds.Value.Top, (int)(ToolTipSize.X + Margin * 2), (int)(ToolTipSize.Y + Margin * 2));
                                b.DrawString(Game1.smallFont, ButtonToolTip, new Vector2(HoveredButtonBounds.Value.Left - Margin - ToolTipSize.X, HoveredButtonBounds.Value.Top + Margin), Color.Black);
                            }
                        }
                    }
                }

                upperRightCloseButton.draw(b);

                if (!Game1.options.hardwareCursor && !Game1.options.gamepadControls)
                {
                    drawMouse(b);
                }
            }
            catch (Exception ex)
            {
                ItemBagsMod.ModInstance.Monitor.Log(string.Format("Unhandled error in ItemBagMenu.Draw: {0}", ex.Message), LogLevel.Error);
            }
        }
Esempio n. 12
0
        public void DrawToolTips(SpriteBatch b)
        {
            if (!IsJojaMember)
            {
                if (HoveredBundleItem != null)
                {
                    Object HoveredItem = GetHoveredItem();
                    if (HoveredItem != null)
                    {
                        Rectangle Location;
                        if (IsNavigatingWithGamepad)
                        {
                            Location = ItemSlotPositions[HoveredBundleItem].GetOffseted(TopLeftScreenPosition);
                        }
                        else
                        {
                            Location = new Rectangle(Game1.getMouseX() - 8, Game1.getMouseY() + 36, 8 + 36, 1);
                        }
                        DrawHelpers.DrawToolTipInfo(b, Location, HoveredItem, true, true, true, true, true, true,
                                                    HoveredBundleItem.Quantity, !HoveredBundleItem.IsCompleted, Color.White);
                    }
                }

                if (HoveredBundleTask != null)
                {
                    Rectangle ToolTipAnchorPoint = TaskHeaderPositions[HoveredBundleTask].GetOffseted(TopLeftScreenPosition);

                    int Padding        = 20;
                    int TaskImageSize  = 96;
                    int RewardIconSize = 48;
                    int RewardWidth    = RewardIconSize + 12 + RewardIconSize;

                    //  Compute header
                    SpriteFont HeaderFont  = Game1.dialogueFont;
                    float      HeaderScale = 1f;
                    string     HeaderText  = !string.IsNullOrEmpty(HoveredBundleTask.TranslatedName) ? HoveredBundleTask.TranslatedName : HoveredBundleTask.Name + " Bundle";
                    Vector2    HeaderSize  = HeaderFont.MeasureString(HeaderText) * HeaderScale;

                    //  Compute description
                    int ReadyToComplete = 0;
                    foreach (BundleItem BI in HoveredBundleTask.Items)
                    {
                        if (!BI.IsCompleted && ItemPlaceholders.TryGetValue(BI, out Object Placeholder) && Placeholder.Stack >= BI.Quantity)
                        {
                            ReadyToComplete++;
                        }
                    }
                    SpriteFont BodyFont  = Game1.smallFont;
                    float      BodyScale = 1.0f;
                    string     BodyText  = HoveredBundleTask.IsCompleted ? ItemBagsMod.Translate("BundleTaskCompletedToolTip") :
                                           ItemBagsMod.Translate("BundleTaskIncompleteToolTip", new Dictionary <string, string>()
                    {
                        { "CompletedCount", HoveredBundleTask.Items.Count(x => x.IsCompleted).ToString() },
                        { "TotalCount", HoveredBundleTask.Items.Count.ToString() },
                        { "ReadyToCompleteCount", ReadyToComplete.ToString() },
                        { "RequiredCount", HoveredBundleTask.RequiredItemCount.ToString() }
                    });
                    Vector2 BodySize = BodyFont.MeasureString(BodyText) * BodyScale;

                    int ToolTipWidth = (int)new List <float>()
                    {
                        TaskImageSize, HeaderSize.X, BodySize.X, RewardWidth
                    }.Max() + Padding * 2;
                    int ToolTipHeight = Padding + TaskImageSize + 16 + (int)HeaderSize.Y + 12 + (int)BodySize.Y + 12 + RewardIconSize + Padding;

                    //  Ensure tooltip is fully visible on screen
                    Rectangle Position = new Rectangle(ToolTipAnchorPoint.Right, ToolTipAnchorPoint.Top, ToolTipWidth, ToolTipHeight);
                    if (Position.Right > Game1.viewport.Size.Width)
                    {
                        Position = new Rectangle(ToolTipAnchorPoint.Left - ToolTipWidth, Position.Top, Position.Width, Position.Height);
                    }
                    if (Position.Bottom > Game1.viewport.Size.Height)
                    {
                        Position = new Rectangle(Position.X, ToolTipAnchorPoint.Bottom - ToolTipHeight, Position.Width, Position.Height);
                    }

                    DrawHelpers.DrawBox(b, Position);

                    int CurrentY = Position.Y + Padding;

                    //  Draw image associated with this task
                    Rectangle TaskImagePosition = new Rectangle(Position.X + (Position.Width - TaskImageSize) / 2, CurrentY, TaskImageSize, TaskImageSize);
                    DrawHelpers.DrawBorder(b, new Rectangle(TaskImagePosition.Left - 4, TaskImagePosition.Top - 4, TaskImagePosition.Width + 8, TaskImagePosition.Height + 8), 4, Color.Black);
                    b.Draw(HoveredBundleTask.ActualLargeIconTexture, TaskImagePosition, HoveredBundleTask.ActualLargeIconPosition, Color.White);
                    CurrentY += TaskImageSize + 16;

                    //  Draw header text (Task's name)
                    Vector2 HeaderPosition = new Vector2(Position.X + (Position.Width - HeaderSize.X) / 2, CurrentY);
                    b.DrawString(HeaderFont, HeaderText, HeaderPosition, Color.Black, 0f, Vector2.Zero, HeaderScale, SpriteEffects.None, 1f);
                    CurrentY += (int)(HeaderSize.Y + 12);

                    //  Draw description text
                    Vector2 BodyPosition = new Vector2(Position.X + (Position.Width - BodySize.X) / 2, CurrentY);
                    b.DrawString(BodyFont, BodyText, BodyPosition, Color.SlateGray, 0f, Vector2.Zero, BodyScale, SpriteEffects.None, 1f);
                    CurrentY += (int)(BodySize.Y + 12);

                    //  Draw reward item
                    Rectangle RewardPosition = new Rectangle(Position.X + (Position.Width - RewardWidth) / 2, CurrentY, RewardWidth, RewardIconSize);
                    b.Draw(TextureHelpers.JunimoNoteTexture, new Rectangle(RewardPosition.X, RewardPosition.Y, RewardIconSize, RewardIconSize), new Rectangle(548, 264, 18, 18), Color.White);
                    if (HoveredBundleTask.Reward != null)
                    {
                        DrawHelpers.DrawItem(b, new Rectangle(RewardPosition.Right - RewardIconSize, RewardPosition.Y, RewardIconSize, RewardIconSize), HoveredBundleTask.Reward.ToItem(), true, true, 1f, 1f, Color.White, Color.White);
                    }
                }
            }
        }