Example #1
0
        public override void draw(SpriteBatch b)
        {
            // Fade the area
            b.Draw(Game1.fadeToBlackRect, Game1.graphics.GraphicsDevice.Viewport.Bounds, Color.Black * 0.75f);

            // Draw the main box, along with the money box
            Game1.drawDialogueBox(this.xPositionOnScreen, this.yPositionOnScreen, this.width, this.height, speaker: false, drawOnlyBox: true, r: 80, g: 123, b: 186);
            Game1.dayTimeMoneyBox.drawMoneyBox(b);

            // See if we're checking out
            if (isCheckingOut)
            {
                b.Draw(JojaResources.GetJojaCheckoutBackground(), new Rectangle(this.xPositionOnScreen + IClickableMenu.borderWidth - 8, this.yPositionOnScreen + IClickableMenu.borderWidth + 56, this.width - (IClickableMenu.borderWidth * 2) + 16, this.height - 128), new Rectangle(0, 0, 150, 200), Color.White);

                // Draw cancel button
                cancelButton.draw(b);

                // Draw item icon, name and quantity
                int subTotal        = 0;
                int stackCount      = 0;
                int uniqueItemCount = 1;

                int   rowStart    = scale == 1f ? 120 : 140;
                int   rowSpacing  = scale == 1f ? 45 : 40;
                float textScale   = scale == 1f ? 1f : 0.5f;
                float itemScaling = scale == 1f ? 0.5f : 0.4f;
                foreach (ISalable item in itemsInCart.Keys)
                {
                    // Draw item
                    item.Stack = itemsInCart[item][1];
                    item.drawInMenu(b, GetScaledVector(80, rowStart + (rowSpacing * uniqueItemCount)), itemScaling, 1f, 0.9f, StackDrawType.Hide, Color.White, drawShadow: false);

                    // Draw name / quantity and price
                    Utility.drawTextWithShadow(b, $"{item.DisplayName} x{item.Stack}", Game1.dialogueFont, new Vector2(this.xPositionOnScreen + this.width / 4, GetScaledYCoordinate(rowStart + 10 + (rowSpacing * uniqueItemCount))), Color.White, textScale, 0.5f, numShadows: 0, shadowIntensity: 0);

                    int stackCost = item.Stack * itemsInCart[item][0];
                    Utility.drawTextWithShadow(b, stackCost + "g", Game1.dialogueFont, new Vector2((int)(this.xPositionOnScreen + this.width - this.width / 6 - IClickableMenu.borderWidth), GetScaledYCoordinate(rowStart + 10 + (rowSpacing * uniqueItemCount))), item == randomSaleItem ? Color.Cyan : Color.White, textScale, 0.5f, numShadows: 0, shadowIntensity: 0);

                    stackCount += item.Stack;
                    subTotal   += stackCost;
                    uniqueItemCount++;
                }

                // Check if purchased item(s) contain Joja Prime, if so offer free shipping
                bool isPurchasingPrimeShipping = itemsInCart.Any(i => (i.Key as Item).ParentSheetIndex == JojaItems.GetJojaPrimeMembershipID()) ? true : false;

                // Draw the shipping options (free 2 day or next day with fee)
                Utility.drawTextWithShadow(b, "Options", Game1.dialogueFont, new Vector2(this.xPositionOnScreen + 85 * scale, (this.yPositionOnScreen + this.height - this.height / 3) - 20 * scale), Color.White, scale, 0.6f, numShadows: 0, shadowIntensity: 0);
                IClickableMenu.drawTextureBox(b, Game1.mouseCursors, new Rectangle(403, 373, 9, 9), this.twoDayShippingButton.bounds.X, this.twoDayShippingButton.bounds.Y, this.twoDayShippingButton.bounds.Width, this.twoDayShippingButton.bounds.Height, isNextDayShipping ? Color.White : Color.Gray, scale * 4f * twoDayShippingButton.scale, false);
                Utility.drawTextWithShadow(b, "Two Day (Free)", Game1.dialogueFont, new Vector2(this.twoDayShippingButton.bounds.X + 12 * scale, this.twoDayShippingButton.bounds.Y + (LocalizedContentManager.CurrentLanguageLatin ? 16 : 12) * scale), Game1.textColor * (isNextDayShipping ? 1f : 0.25f), textScale, -1f, 0, 0, 0, 0);

                string nextDayShippingText = hasPrimeShipping || isPurchasingPrimeShipping ? $"Next Day (Free)" : $"Next Day (+{nextDayShippingFee}%)";
                IClickableMenu.drawTextureBox(b, Game1.mouseCursors, new Rectangle(403, 373, 9, 9), this.nextDayShippingButton.bounds.X, this.nextDayShippingButton.bounds.Y, this.nextDayShippingButton.bounds.Width, this.nextDayShippingButton.bounds.Height, isNextDayShipping ? Color.Gray : Color.White, scale * 4f * nextDayShippingButton.scale, false);
                Utility.drawTextWithShadow(b, nextDayShippingText, Game1.dialogueFont, new Vector2(this.nextDayShippingButton.bounds.X + 12 * scale, this.nextDayShippingButton.bounds.Y + (LocalizedContentManager.CurrentLanguageLatin ? 16 : 12) * scale), Game1.textColor * (isNextDayShipping ? 0.25f : 1f), textScale, -1f, 0, 0, 0, 0);

                // Draw the subtotal
                //Utility.drawTextWithShadow(b, $"Subtotal:", Game1.dialogueFont, GetScaledVector(this.width - SpriteText.getWidthOfString($"Subtotal:{subTotal}g") - 50, this.height - 320), Color.LightGray, scale, 0.6f, numShadows: 0, shadowIntensity: 0);
                //Utility.drawTextWithShadow(b, $"{subTotal}g", Game1.dialogueFont, GetScaledVector(this.width - SpriteText.getWidthOfString($"{subTotal}g") - 75, this.height - 320), Color.LightGray, scale, 0.6f, numShadows: 0, shadowIntensity: 0);

                // Draw the shipping costs
                int    shippingCosts    = isNextDayShipping && !hasPrimeShipping && !isPurchasingPrimeShipping ? subTotal / nextDayShippingFee : 0;
                string shippingCostText = shippingCosts == 0 ? "FREE" : $"{shippingCosts}g";
                Utility.drawTextWithShadow(b, $"Shipping:", Game1.dialogueFont, new Vector2(this.xPositionOnScreen + this.width / 2 + 20 * scale, (this.yPositionOnScreen + this.height - this.height / 3) - 20 * scale), Color.White, scale, 0.6f, numShadows: 0, shadowIntensity: 0);
                Utility.drawTextWithShadow(b, shippingCostText, Game1.dialogueFont, new Vector2(this.xPositionOnScreen + this.width - SpriteText.getWidthOfString(shippingCostText) * scale - (shippingCostText == "FREE" ? 75 * scale : 25), (this.yPositionOnScreen + this.height - this.height / 3) - 20 * scale), Color.White, scale, 0.6f, numShadows: 0, shadowIntensity: 0);

                // Draw the total
                int total = subTotal + shippingCosts;
                Utility.drawTextWithShadow(b, $"Total:", Game1.dialogueFont, new Vector2(this.xPositionOnScreen + 85 * scale, this.purchaseButton.bounds.Y + (LocalizedContentManager.CurrentLanguageLatin ? 16 : 12) * scale), Color.Gold, scale, 0.6f, numShadows: 0, shadowIntensity: 0);
                Utility.drawTextWithShadow(b, $"{total}g", Game1.dialogueFont, new Vector2(this.xPositionOnScreen + (85 * scale + SpriteText.getWidthOfString($"Total:") * scale), this.purchaseButton.bounds.Y + (LocalizedContentManager.CurrentLanguageLatin ? 16 : 12) * scale), Color.Gold, scale, 0.6f, numShadows: 0, shadowIntensity: 0);

                // Draw the purchase button
                canAffordOrder = total <= Game1.player.Money ? true : false;
                IClickableMenu.drawTextureBox(b, Game1.mouseCursors, new Rectangle(403, 373, 9, 9), this.purchaseButton.bounds.X, this.purchaseButton.bounds.Y, this.purchaseButton.bounds.Width, this.purchaseButton.bounds.Height, canAffordOrder ? Color.White : Color.Gray, scale * 4f * purchaseButton.scale, false);
                Utility.drawTextWithShadow(b, $"Purchase Order", Game1.dialogueFont, new Vector2(this.purchaseButton.bounds.X + 12 * scale, this.purchaseButton.bounds.Y + (LocalizedContentManager.CurrentLanguageLatin ? 16 : 12) * scale), Game1.textColor * (canAffordOrder ? 1f : 0.25f), textScale, -1f, 0, 0, 0, 0);

                // Draw the mouse
                this.drawMouse(b);

                return;
            }

            // Draw the custom store BG
            // this.width - (IClickableMenu.borderWidth * 2) - 12 to account for width shift, this.height - 128 due to drawDialogueBox method adding 128 to height
            b.Draw(JojaResources.GetJojaSiteBackground(), new Rectangle(this.xPositionOnScreen + IClickableMenu.borderWidth - 8, this.yPositionOnScreen + IClickableMenu.borderWidth + 56, this.width - (IClickableMenu.borderWidth * 2) + 16, this.height - 128), new Rectangle(0, 0, 150, 200), Color.White);
            IClickableMenu.drawTextureBox(b, sourceSheet, new Rectangle(13, 64, 3, 3), this.xPositionOnScreen + IClickableMenu.borderWidth - 8, this.yPositionOnScreen + IClickableMenu.borderWidth + 56, this.width - (IClickableMenu.borderWidth * 2) + 16, (int)(70 * scale), Color.White, 1f, drawShadow: false);

            // Draw the current unique amount of items in cart
            cartQuantity = drawCartQuantity(sourceSheet, new Rectangle(0, 41, 5, 7));
            cartQuantity.draw(b);

            // Draw the usage instructions
            //IClickableMenu.drawTextureBox(b, sourceSheet, new Rectangle(144, 576, 76, 64), this.xPositionOnScreen + 100, this.yPositionOnScreen + 600, 76, 64, Color.White, scale, drawShadow: false);
            //SpriteText.drawString(b, "to order", this.xPositionOnScreen + 100, this.yPositionOnScreen + 600, 999999, -1, 999999, 1f, 0.88f, junimoText: false, -1, "", 4);
            //SpriteText.drawString(b, "to remove", (this.xPositionOnScreen + this.width) - SpriteText.getWidthOfString("Right Click to remove"), this.yPositionOnScreen + 600, 999999, -1, 999999, 1f, 0.88f, junimoText: false, -1, "", 4);

            // Draw the general clickables
            foreach (ClickableTextureComponent clickable in clickables)
            {
                clickable.draw(b);
            }

            // Draw the checkout button
            checkoutButton.draw(b, itemsInCart.Count > 0 ? Color.White : Color.Black, 0.99f);

            // Draw the scroll bar
            IClickableMenu.drawTextureBox(b, sourceSheet, new Rectangle(0, 74, 6, 6), scrollBarRunner.X, scrollBarRunner.Y, scrollBarRunner.Width, scrollBarRunner.Height, Color.White, 4f, drawShadow: false);
            scrollBar.draw(b);

            // Draw the sale button
            randomSaleButton.draw(b);

            if (randomSaleItem is Furniture)
            {
                (randomSaleItem as Furniture).drawInMenu(b, new Vector2(randomSaleButton.bounds.Center.X - (25 * scale) + (scale == 1f ? -7 : -13), randomSaleButton.bounds.Center.Y - (25 * scale) + (scale == 1f ? -8 : -19)), 0.75f, 1f, 0.9f, StackDrawType.Hide, Color.White, drawShadow: false);
            }
            else if (randomSaleItem is Wallpaper)
            {
                if ((randomSaleItem as Wallpaper).isFloor)
                {
                    (randomSaleItem as Wallpaper).drawInMenu(b, new Vector2(randomSaleButton.bounds.Center.X - (25 * scale) + (scale == 1f ? -7 : -11), randomSaleButton.bounds.Center.Y - (25 * scale) + (scale == 1f ? -8 : -2)), 0.6f, 1f, 0.9f, StackDrawType.Hide, Color.White, drawShadow: false);
                }
                else
                {
                    (randomSaleItem as Wallpaper).drawInMenu(b, new Vector2(randomSaleButton.bounds.Center.X - (25 * scale) + (scale == 1f ? -7 : -14), randomSaleButton.bounds.Center.Y - (25 * scale) + (scale == 1f ? -8 : -7)), 0.6f, 1f, 0.9f, StackDrawType.Hide, Color.White, drawShadow: false);
                }
            }
            else
            {
                randomSaleItem.drawInMenu(b, new Vector2(randomSaleButton.bounds.Center.X - (25 * scale) + (scale == 1f ? -2 : -8), randomSaleButton.bounds.Center.Y - (25 * scale) + (scale == 1f ? -2 : -9)), 0.6f, 1f, 0.9f, StackDrawType.Hide, Color.White, drawShadow: false);
            }
            //randomSaleItem.drawInMenu(b, new Vector2(randomSaleButton.bounds.Center.X - 25 * scale, randomSaleButton.bounds.Center.Y - 25 * scale), scale * 0.5f, 1f, 0.9f, StackDrawType.Hide, Color.White, drawShadow: false);

            // Draw the individual store buttons
            foreach (ClickableComponent button in forSaleButtons)
            {
                int buttonPosition = forSaleButtons.IndexOf(button) + (currentItemIndex * 2);
                if (buttonPosition >= forSale.Count)
                {
                    continue;
                }

                // Draw the button grid
                IClickableMenu.drawTextureBox(b, sourceSheet, new Rectangle(0, 48, 15, 15), button.bounds.X, button.bounds.Y, button.bounds.Width, button.bounds.Height, Color.White, scale * 4f, drawShadow: false);

                // Get the quantity that is in the cart (if any)
                int currentlyInCart = 0;
                if (itemsInCart.ContainsKey(forSale[buttonPosition]))
                {
                    currentlyInCart = itemsInCart[forSale[buttonPosition]][1];
                }

                // Draw the item for sale
                float itemScale   = scale == 1f ? 1f : 0.6f;
                Item  itemForSale = forSale[buttonPosition] as Item;
                if (itemForSale is Furniture)
                {
                    (itemForSale as Furniture).drawInMenu(b, new Vector2(button.bounds.X + (button.bounds.Width / 12 * itemScale) + (itemScale == 1f ? 0 : -5), button.bounds.Y + (button.bounds.Height / 8 * itemScale) + (itemScale == 1f ? 2 : -5)), itemScale, 1f, 0.9f, StackDrawType.Hide, Color.White * (itemsInCart.Count < maxUniqueCartItems || currentlyInCart > 0 ? 1f : 0.25f), drawShadow: false);
                }
                else if (itemForSale is Wallpaper)
                {
                    (itemForSale as Wallpaper).drawInMenu(b, new Vector2(button.bounds.X + (button.bounds.Width / 12 * itemScale) + (itemScale == 1f ? 0 : -5), button.bounds.Y + (button.bounds.Height / 8 * itemScale) + (itemScale == 1f ? 2 : -5)), itemScale, 1f, 0.9f, StackDrawType.Hide, Color.White * (itemsInCart.Count < maxUniqueCartItems || currentlyInCart > 0 ? 1f : 0.25f), drawShadow: false);
                }
                else
                {
                    itemForSale.drawInMenu(b, new Vector2(button.bounds.X + (button.bounds.Width / 12 * itemScale), button.bounds.Y + (button.bounds.Height / 8 * itemScale) + (itemScale == 1f ? 2 : -2)), itemScale, 1f, 0.9f, StackDrawType.Hide, Color.White * (itemsInCart.Count < maxUniqueCartItems || currentlyInCart > 0 ? 1f : 0.25f), drawShadow: false);
                }

                // Draw the quantity in the cart
                Utility.drawTextWithShadow(b, $"In Cart: {currentlyInCart}", Game1.dialogueFont, new Vector2(button.bounds.X + (button.bounds.Width / 4) + 15 * scale, button.bounds.Y + 10), Color.White * (itemsInCart.Count < maxUniqueCartItems || currentlyInCart > 0 ? 1f : 0.5f), scale == 1f ? 0.9f : 0.5f, 0.88f, numShadows: 0, shadowIntensity: 0);

                // Check if item is on sale, if so then add visual marker
                float coinScale = scale == 1f ? 3.75f : 2f;
                float textScale = scale == 1f ? 0.9f : 0.5f;
                if (itemForSale == randomSaleItem)
                {
                    // Draw the (discounted) price
                    string price = ((int)(itemPriceAndStock[itemForSale][0] - (itemPriceAndStock[itemForSale][0] * randomSalePercentageOff))).ToString();
                    Utility.drawTextWithShadow(b, "-" + (randomSalePercentageOff * 100) + "%", Game1.dialogueFont, new Vector2(button.bounds.X + (button.bounds.Width / 4) + 15 * scale, button.bounds.Y + button.bounds.Height - (SpriteText.getHeightOfString("-" + (randomSalePercentageOff * 100) + "%") * textScale) - (6 * scale)), Color.Cyan * (itemsInCart.Count < maxUniqueCartItems || currentlyInCart > 0 ? 1f : 0.5f), textScale, 0.6f, numShadows: 0, shadowIntensity: 0);
                    Utility.drawTextWithShadow(b, price, Game1.dialogueFont, new Vector2(button.bounds.X + button.bounds.Width - (SpriteText.getWidthOfString(price) * textScale) - (9 * coinScale) - (6 * scale), button.bounds.Y + button.bounds.Height - (SpriteText.getHeightOfString(price) * textScale) - (6 * scale)), Color.Cyan * (itemsInCart.Count < maxUniqueCartItems || currentlyInCart > 0 ? 1f : 0.5f), textScale, 0.6f, numShadows: 0, shadowIntensity: 0);
                    Utility.drawWithShadow(b, Game1.mouseCursors, new Vector2(button.bounds.X + button.bounds.Width - (9 * coinScale) - (10 * scale), button.bounds.Y + button.bounds.Height - (10 * coinScale) - (7 * scale)), new Rectangle(193, 373, 9, 10), Color.White * (itemsInCart.Count < maxUniqueCartItems || currentlyInCart > 0 ? 1f : 0.25f), 0f, Vector2.Zero, coinScale, flipped: false, 1f, -1, -1, 0f);

                    // Draw sale marker
                    Utility.drawWithShadow(b, sourceSheet, new Vector2(button.bounds.Right - (14 * scale * 3f) - (12 * scale), button.bounds.Y + (12 * scale)), new Rectangle(0, 80, 14, 7), Color.White, 0f, Vector2.Zero, scale * 3f, flipped: false, 1f, -1, -1, 0f);
                }
                else
                {
                    // Draw the price
                    string price = itemPriceAndStock[itemForSale][0].ToString();
                    Utility.drawTextWithShadow(b, price, Game1.dialogueFont, new Vector2(button.bounds.X + button.bounds.Width - (SpriteText.getWidthOfString(price) * textScale) - (9 * coinScale) - (6 * scale), button.bounds.Y + button.bounds.Height - (SpriteText.getHeightOfString(price) * textScale) - (6 * scale)), new Color(251, 249, 78) * (itemsInCart.Count < maxUniqueCartItems || currentlyInCart > 0 ? 1f : 0.5f), textScale, 0.6f, numShadows: 0, shadowIntensity: 0);
                    Utility.drawWithShadow(b, Game1.mouseCursors, new Vector2(button.bounds.X + button.bounds.Width - (9 * coinScale) - (10 * scale), button.bounds.Y + button.bounds.Height - (10 * coinScale) - (7 * scale)), new Rectangle(193, 373, 9, 10), Color.White * (itemsInCart.Count < maxUniqueCartItems || currentlyInCart > 0 ? 1f : 0.25f), 0f, Vector2.Zero, coinScale, flipped: false, 1f, -1, -1, 0f);
                }
            }

            // Draw the tooltip
            if (!this.hoverText.Equals(""))
            {
                if (this.hoveredItem is StardewValley.Object && (bool)(this.hoveredItem as StardewValley.Object).isRecipe)
                {
                    IClickableMenu.drawToolTip(b, " ", this.boldTitleText, this.hoveredItem as Item, false, -1, 0, -1, -1, new CraftingRecipe(this.hoveredItem.Name.Replace(" Recipe", "")), (this.hoverPrice > 0) ? this.hoverPrice : (-1));
                }
                else
                {
                    IClickableMenu.drawToolTip(b, this.hoverText, this.boldTitleText, this.hoveredItem as Item, false, -1, 0, -1, -1, null, (this.hoverPrice > 0) ? this.hoverPrice : (-1));
                }
            }

            this.upperRightCloseButton.draw(b);
            this.drawMouse(b);
        }
Example #2
0
        public static bool CreateMailOrder(Farmer recipient, int daysToWait, List <Item> packagedItems)
        {
            try
            {
                // Check if packagedItems contains Joja Prime item
                int jojaPrimeID = JojaItems.GetJojaPrimeMembershipID();
                if (packagedItems.Any(i => i.ParentSheetIndex == jojaPrimeID))
                {
                    // Remove Joja Prime from the store
                    JojaResources.RemoveFromJojaOnlineStock(packagedItems.First(i => i.ParentSheetIndex == jojaPrimeID));

                    // Now send out mail with JojaPrimeShipping id
                    SendMail(recipient, "JojaPrimeShippingInfo", $"Valued Member,^^Thank you for purchasing Joja Prime. You are now able to use free next day delivery on Joja Online.^^We look forward to your continued business.^^- Joja Co.");

                    // Add JojaPrimeShipping mailID to the player's received mail so the flags recognize the membership has been purchased
                    // Otherwise the player will not have the membership until they read the mail the next day
                    Game1.MasterPlayer.mailReceived.Add("JojaPrimeShipping");

                    // Set the hasPrimeShipping to true manually, as it otherwise wouldn't update until the next day
                    JojaSite.SetPrimeShippingStatus(true);

                    // Remove Joja Prime from the list of shipped items, as we actually don't want to ship it
                    packagedItems = packagedItems.Where(i => i.ParentSheetIndex != jojaPrimeID).ToList();

                    // Skip rest of logic of there are no more items to ship due to removing Joja Prime
                    if (packagedItems.Count == 0)
                    {
                        return(true);
                    }
                }

                // Determine order number
                int orderNumber = 0;
                while (MailDao.FindLetter($"JojaMailOrder[#{orderNumber}]") != null || recipient.mailReceived.Contains($"JojaMailOrder[#{orderNumber}]") || IsOrderNumberScheduled(recipient, orderNumber))
                {
                    orderNumber++;
                }
                string mailOrderID = $"JojaMailOrder[#{orderNumber}]";

                // Generate mail message
                string message = $"Valued Customer,^^Thank you for using Joja Online. Your items for order #{orderNumber:0000} are packaged below.^^We look forward to your continued business.^^- Joja Co.";

                if (JojaSite.GetMembershipStatus() || JojaSite.GetPrimeShippingStatus())
                {
                    message = $"Valued Member,^^Thank you for using Joja Online. Your items for order #{orderNumber:0000} are packaged below.^^We look forward to your continued business.^^- Joja Co.";
                }

                // Determine the deliveryDate
                int deliveryDate = daysToWait + Game1.dayOfMonth > 28 ? daysToWait : daysToWait + Game1.dayOfMonth;

                // Need to save this mail data if it can't be delivered before shutdown
                recipient.mailForTomorrow.Add($"{mailOrderID}[{message}][{deliveryDate}][{String.Join(", ", packagedItems.Select(i => $"[{i.Name}, {i.category}, {i.parentSheetIndex}, {i.Stack}]"))}]");

                monitor.Log($"JojaMail order [#{orderNumber}] created with delivery date of [{deliveryDate}] {String.Join(", ", packagedItems.Select(i => $"[{i.Name}, {i.category}, {i.parentSheetIndex}, {i.Stack}]"))}!", LogLevel.Debug);
            }
            catch (Exception ex)
            {
                return(false);
            }

            return(true);
        }
        public static void SetJojaOnlineStock(Dictionary <string, int> nameToPriceOverrides, bool doStockAllSeedsBeforeYearOne, bool doCopyPiereeSeedStock)
        {
            // Clone the current stock
            jojaOnlineStock = new Dictionary <ISalable, int[]>();
            cachedItemNames = new List <string>();

            // Add wood, stone and hardwood
            AddToJojaOnlineStock(new Object(Vector2.Zero, 388, int.MaxValue));
            AddToJojaOnlineStock(new Object(Vector2.Zero, 390, int.MaxValue));
            AddToJojaOnlineStock(new Object(Vector2.Zero, 709, int.MaxValue), 500);

            // Add coal
            AddToJojaOnlineStock(new Object(Vector2.Zero, 382, int.MaxValue));

            // Add battery pack
            AddToJojaOnlineStock(new Object(Vector2.Zero, 390, int.MaxValue), 2500);

            // Add cloth
            AddToJojaOnlineStock(new Object(Vector2.Zero, 428, int.MaxValue), 2000);

            // Add energy tonic
            AddToJojaOnlineStock(new Object(Vector2.Zero, 349, int.MaxValue));

            // Add some of Pierre's goods (if available)
            try
            {
                foreach (Item item in new SeedShop().shopStock().Keys)
                {
                    if (item is null)
                    {
                        continue;
                    }

                    if (item.parentSheetIndex == 368)
                    {
                        AddToJojaOnlineStock(new Object(Vector2.Zero, item.parentSheetIndex, int.MaxValue), 100);
                    }
                    else if (item.parentSheetIndex == 369)
                    {
                        AddToJojaOnlineStock(new Object(Vector2.Zero, item.parentSheetIndex, int.MaxValue), 150);
                    }
                    else if (item.parentSheetIndex == 370)
                    {
                        AddToJojaOnlineStock(new Object(Vector2.Zero, item.parentSheetIndex, int.MaxValue), 100);
                    }
                    else if (item.parentSheetIndex == 371)
                    {
                        AddToJojaOnlineStock(new Object(Vector2.Zero, item.parentSheetIndex, int.MaxValue), 150);
                    }
                    else if (item.parentSheetIndex == 465)
                    {
                        AddToJojaOnlineStock(new Object(Vector2.Zero, item.parentSheetIndex, int.MaxValue), 100);
                    }
                    else if (item.parentSheetIndex == 466)
                    {
                        AddToJojaOnlineStock(new Object(Vector2.Zero, item.parentSheetIndex, int.MaxValue), 150);
                    }
                    else if (item.category == -74 && doCopyPiereeSeedStock)                     // Is a seed, add it to the stock
                    {
                        modMonitor.Log($"Adding {item.Name}", LogLevel.Trace);
                        AddToJojaOnlineStock(new Object(Vector2.Zero, item.parentSheetIndex, int.MaxValue));
                    }
                }
            }
            catch (ArgumentNullException ex)
            {
                modMonitor.Log($"Unable to load some of Pierre's goods, SeedShop seems to be empty or null: {ex}", LogLevel.Warn);
            }

            // Add some of Marnie's goods (only hay for now)
            AddToJojaOnlineStock(new Object(Vector2.Zero, 178, int.MaxValue), 50);

            // Add the current JojaMart items
            Utility.getJojaStock().ToList().ForEach(x => AddToJojaOnlineStock(x.Key));

            // If past year one (or doStockAllSeedsBeforeYearOne), unlock all seeds (that aren't in the current season due to initial cloning)
            if (Game1.player.yearForSaveGame > 1 || doStockAllSeedsBeforeYearOne)
            {
                modMonitor.Log("Loading JojaMart's stock for all seasons for JojaOnline", LogLevel.Debug);
                if (!Game1.currentSeason.Equals("spring"))
                {
                    AddToJojaOnlineStock(new Object(Vector2.Zero, 472, int.MaxValue));
                    AddToJojaOnlineStock(new Object(Vector2.Zero, 473, int.MaxValue));
                    AddToJojaOnlineStock(new Object(Vector2.Zero, 474, int.MaxValue));
                    AddToJojaOnlineStock(new Object(Vector2.Zero, 475, int.MaxValue));
                    AddToJojaOnlineStock(new Object(Vector2.Zero, 427, int.MaxValue));
                    AddToJojaOnlineStock(new Object(Vector2.Zero, 429, int.MaxValue));
                    AddToJojaOnlineStock(new Object(Vector2.Zero, 477, int.MaxValue));
                }
                if (!Game1.currentSeason.Equals("summer"))
                {
                    AddToJojaOnlineStock(new Object(Vector2.Zero, 480, int.MaxValue));
                    AddToJojaOnlineStock(new Object(Vector2.Zero, 482, int.MaxValue));
                    AddToJojaOnlineStock(new Object(Vector2.Zero, 483, int.MaxValue));
                    AddToJojaOnlineStock(new Object(Vector2.Zero, 484, int.MaxValue));
                    AddToJojaOnlineStock(new Object(Vector2.Zero, 479, int.MaxValue));
                    AddToJojaOnlineStock(new Object(Vector2.Zero, 302, int.MaxValue));
                    AddToJojaOnlineStock(new Object(Vector2.Zero, 453, int.MaxValue));
                    AddToJojaOnlineStock(new Object(Vector2.Zero, 455, int.MaxValue));
                    AddToJojaOnlineStock(new Object(431, int.MaxValue, isRecipe: false, 100));
                }
                if (!Game1.currentSeason.Equals("fall"))
                {
                    AddToJojaOnlineStock(new Object(Vector2.Zero, 487, int.MaxValue));
                    AddToJojaOnlineStock(new Object(Vector2.Zero, 488, int.MaxValue));
                    AddToJojaOnlineStock(new Object(Vector2.Zero, 483, int.MaxValue));
                    AddToJojaOnlineStock(new Object(Vector2.Zero, 490, int.MaxValue));
                    AddToJojaOnlineStock(new Object(Vector2.Zero, 299, int.MaxValue));
                    AddToJojaOnlineStock(new Object(Vector2.Zero, 301, int.MaxValue));
                    AddToJojaOnlineStock(new Object(Vector2.Zero, 492, int.MaxValue));
                    AddToJojaOnlineStock(new Object(Vector2.Zero, 491, int.MaxValue));
                    AddToJojaOnlineStock(new Object(Vector2.Zero, 493, int.MaxValue));
                    AddToJojaOnlineStock(new Object(431, int.MaxValue, isRecipe: false, 100));
                    AddToJojaOnlineStock(new Object(Vector2.Zero, 425, int.MaxValue));
                }
            }

            // Add Auto-Petter (normally only available from completing Joja route)
            AddToJojaOnlineStock(new Object(Vector2.Zero, 272), 50000);

            // Load in any Joja Prime Membership items from JojaItems
            int primeMembershipItemID = JojaItems.GetJojaPrimeMembershipID();

            if (primeMembershipItemID > 0 && !HasPrimeMembership())
            {
                AddToJojaOnlineStock(new Object(primeMembershipItemID, 1, false, -1, 0), 500000, 1);
            }

            // TODO: Load in any modded seeds
            // Need a way to get the store they are added to, as Json Asset adds the seeds OnMenuChanged...
            // Otherwise all the modded seeds will be added, regardless if they are available...

            /*
             * if (JojaItems.IsJsonAssetApiConnected())
             * {
             *      foreach (KeyValuePair<string, int> nameToID in JojaItems.GetJsonAssetApi().GetAllCropIds())
             * {
             *              Object obj = new Object(Vector2.Zero, nameToID.Value, int.MaxValue);
             *              if (obj != null && obj.category == -74) // Is a seed
             *              {
             *
             *              }
             * }
             * }
             */

            // Override the prices if the user has given us any
            OverridePrices(nameToPriceOverrides);
        }