public static void updateItemListAfterShop(object sender, StardewModdingAPI.Events.MenuChangedEventArgs e) { if (e.OldMenu is ShopMenu sm && lastInventoryId != null && itemLists.ContainsKey(lastInventoryId)) { Dictionary <ISalable, int[]> itemPriceAndStock = sm.itemPriceAndStock; foreach (Item item in itemLists[lastInventoryId]) { Item i = item.getOne(); int sold = 0; if (itemPriceAndStock.ContainsKey(i)) { sold = item.Stack - itemPriceAndStock[i][1]; item.Stack = itemPriceAndStock[i][1]; } else { sold = item.Stack; item.Stack = 0; } if (sm.portraitPerson is NPC npc && npc.Name == "PlayerShop") { long umid = long.Parse(sm.portraitPerson.endOfRouteMessage.Value); if (Game1.getFarmer(umid) is Farmer f) { ShopMenu.chargePlayer(f, sm.getCurrency(), -(i.salePrice() * sold)); } } } itemLists[lastInventoryId].RemoveAll(it => it.Stack <= 0); lastInventoryId = null; } }
internal static void GiftToNpc(string npcName) { NPC npc = Game1.getCharacterFromName(npcName); Farmer who = Game1.player; string giftName = who.ActiveObject.DisplayName; npc.receiveGift(who.ActiveObject, who, true, 1, DataLoader.ModConfig.ShowDialogOnItemDelivery); ShopMenu.chargePlayer(who, 0, DataLoader.ModConfig.GiftServiceFee); who.reduceActiveItemByOne(); who.completeQuest(25); if (!DataLoader.ModConfig.ShowDialogOnItemDelivery) { Game1.drawObjectDialogue(DataLoader.I18N.Get("Shipment.Gift.GiftSent", new { Gift = giftName, Npc = npc.displayName })); } if (DataLoader.ModConfig.EnableJealousyFromMailedGifts) { if (npc.datable.Value && who.spouse != null && !who.spouse.Contains(npc.Name) && !who.spouse.Contains("Krobus") && Utility.isMale(who.spouse) == Utility.isMale(npc.Name) && Game1.random.NextDouble() < 0.3 - (double)((float)who.LuckLevel / 100f) - who.DailyLuck && !npc.isBirthday(Game1.currentSeason, Game1.dayOfMonth) && who.friendshipData[npc.Name].IsDating()) { NPC spouse = Game1.getCharacterFromName(who.spouse); who.changeFriendship(-30, spouse); spouse.CurrentDialogue.Clear(); spouse.CurrentDialogue.Push(new Dialogue(Game1.content.LoadString("Strings\\StringsFromCSFiles:NPC.cs.3985", npc.displayName), spouse)); } } }
private void BuyTempTool(Farmer who) { // NOTE: there's no thread safe method for money transactions, so I suppose the game doesn't care about it as well? // TODO: handle upgradeLevel so rented tool is not always the cheapest Item toolToBuy = this.GetRentedToolByTool(GetToolBeingUpgraded(who)); if (toolToBuy == null) { return; } int toolCost = this.GetToolCost(toolToBuy); if (who.money >= toolCost && who.freeSpotsInInventory() > 0) { ShopMenu.chargePlayer(who, 0, toolCost); who.addItemToInventory(toolToBuy); this.shouldCreateSucceededToRentTools = true; } else { this.shouldCreateFailedToRentTools = true; } }
/// <summary>Does the action.</summary> /// <param name="amount">Number of items.</param> /// <param name="clickLocation">Where the player clicked (i.e., when selecting item to split).</param> public override void PerformAction(int amount, Point clickLocation) { amount = Math.Min(amount, this.ClickedItem.Stack); this.Amount = amount; // Remove if we don't need to carry this around // Sell item int price = CalculateSalePrice(this.ClickedItem, amount); ShopMenu.chargePlayer(Game1.player, this.ShopCurrencyType, price); Log.Trace($"[{nameof(SellAction)}.{nameof(PerformAction)}] Charged player {price} for {amount} of {this.ClickedItem.Name}"); // Update the stack amount/remove the item var actualInventory = this.InvMenu.actualInventory; var index = actualInventory.IndexOf(this.ClickedItem); if (index >= 0 && index < actualInventory.Count) { int amountRemaining = this.ClickedItem.Stack - amount; if (amountRemaining > 0) { actualInventory[index].Stack = amountRemaining; } else { actualInventory[index] = null; } } Game1.playSound("purchaseClick"); if (amount < 1) { return; } Animate(amount, clickLocation); }
public static bool mailbox() { try { if (Game1.player.mailbox.Count == 0 && Game1.player.CurrentTool is Tool tool) { if (Game1.player.toolBeingUpgraded.Value == null) { if (tool is Axe || tool is Pickaxe || tool is Hoe || tool is WateringCan) { Dictionary <ISalable, int[]> blacksmithUpgradeStock = Utility.getBlacksmithUpgradeStock(Game1.player); int[] cost = blacksmithUpgradeStock .Where(s => s.Key.GetType() == tool.GetType()) .Select(s => s.Value) .FirstOrDefault(); if (cost != null) { int price = cost[0]; int barIndex = cost[2]; const int barCount = 5; if (Game1.player.Money >= price) { if (Game1.player.hasItemInInventory(barIndex, barCount)) { ShopMenu.chargePlayer(Game1.player, 0, price); Game1.player.removeItemsFromInventory(barIndex, barCount); Game1.drawObjectDialogue(DataLoader.I18N.Get("Shipment.Clint.UpgradeLetter.ToolSent", new { Tool = tool.DisplayName })); tool.UpgradeLevel++; Game1.player.removeItemFromInventory(tool); Game1.player.toolBeingUpgraded.Value = tool; Game1.player.daysLeftForToolUpgrade.Value = 2; Game1.playSound("parry"); } else { Game1.drawObjectDialogue(DataLoader.I18N.Get("Shipment.Clint.UpgradeLetter.NoBars", new { Tool = tool.DisplayName })); } } else { Game1.drawObjectDialogue(DataLoader.I18N.Get("Shipment.Clint.UpgradeLetter.NoMoney", new { Tool = tool.DisplayName })); } return(false); } } } } } catch (Exception e) { MailServicesModEntry.ModMonitor.Log("Error trying to send the tool to upgrade.", LogLevel.Error); MailServicesModEntry.ModMonitor.Log($"The error message above:{e.Message}", LogLevel.Trace); } return(true); }
/// <summary>Does the action.</summary> /// <param name="amount">Number of items.</param> /// <param name="clickLocation">Where the player clicked.</param> public override void PerformAction(int amount, Point clickLocation) { amount = Math.Min(amount, this.ClickedItem.Stack); this.Amount = amount; // Remove if we don't need to carry this around // Sell item int price = CalculateSalePrice(this.ClickedItem, amount); ShopMenu.chargePlayer(Game1.player, this.ShopCurrencyType, price); this.Monitor.Log($"Charged player {price} for {amount} of {this.ClickedItem.Name}", LogLevel.Trace); // Update the stack amount/remove the item var actualInventory = this.Inventory.actualInventory; var index = actualInventory.IndexOf(this.ClickedItem); if (index >= 0 && index < actualInventory.Count) { int amountRemaining = this.ClickedItem.Stack - amount; if (amountRemaining > 0) { actualInventory[index].Stack = amountRemaining; } else { actualInventory[index] = null; } } Game1.playSound("purchaseClick"); // The animation seems to only play when we sell 1 if (amount == 1) { // Play the sell animation var animationsField = this.Reflection.GetField <List <TemporaryAnimatedSprite> >(this.NativeShopMenu, "animations"); var animations = animationsField.GetValue(); // Messy because it's a direct copy-paste from the source code Vector2 value = this.Inventory.snapToClickableComponent(clickLocation.X, clickLocation.Y); animations.Add(new TemporaryAnimatedSprite(Game1.debrisSpriteSheet.Name, new Rectangle(Game1.random.Next(2) * Game1.tileSize, 256, Game1.tileSize, Game1.tileSize), 9999f, 1, 999, value + new Vector2(32f, 32f), false, false) { alphaFade = 0.025f, motion = Utility.getVelocityTowardPoint(new Point((int)value.X + 32, (int)value.Y + 32), Game1.dayTimeMoneyBox.position + new Vector2(96f, 196f), 12f), acceleration = Utility.getVelocityTowardPoint(new Point((int)value.X + 32, (int)value.Y + 32), Game1.dayTimeMoneyBox.position + new Vector2(96f, 196f), 0.5f) }); animationsField.SetValue(animations); } }
/// <summary> /// To call when the items were recovered. /// Charge the player and clear the lost items list if needed. /// </summary> public static void ItemsRecovered() { Dictionary <ISalable, int[]> adventureRecoveryStock = Utility.getAdventureRecoveryStock(); RecoveryConfig recoveryConfig = DataLoader.GetRecoveryConfig(Game1.player); _itemsToRecover.Value.ForEach(item => { if (!recoveryConfig.RecoverForFree) { ShopMenu.chargePlayer(Game1.player, 0, adventureRecoveryStock[item][0]); } Game1.player.itemsLostLastDeath.Remove(item); }); if (!recoveryConfig.DisableClearLostItemsOnRandomRecovery && !recoveryConfig.RecoverAllItems) { Game1.player.itemsLostLastDeath.Clear(); } _itemsToRecover.Value = null; }
/// <summary>Attach an onSell callback to a ShopMenu, while keeping the default sell behavior.</summary> /// <param name="shop">The ShopMenu.</param> /// <param name="onSell">The callback to be attached. A return value of true exits the menu.</param> public static void AttachQuietSellCallback(ShopMenu shop, Func <ISalable, bool> onSell) { Func <ISalable, bool> origOnSell = shop.onSell; shop.onSell = delegate(ISalable salable) { bool exit = onSell(salable); if (origOnSell != null) { return(origOnSell(salable) || exit); } else if (salable is Item item) { ISalable?buybackItem = null; float sellPercentage = (float?)SellPercentageField.GetValue(shop) ?? 1f; int sellPrice; if (item is SObject obj) { sellPrice = (int)(obj.sellToStorePrice() * sellPercentage); } else { sellPrice = (int)(item.salePrice() * sellPercentage / 2); } ShopMenu.chargePlayer(Game1.player, shop.currency, -sellPrice * item.Stack); if (shop.CanBuyback()) { buybackItem = shop.AddBuybackItem(item, sellPrice, item.Stack); } if (item is SObject && ((SObject)item).Edibility != -300) { if (buybackItem != null && shop.buyBackItemsToResellTomorrow.ContainsKey(buybackItem)) { shop.buyBackItemsToResellTomorrow[buybackItem].Stack += item.Stack; } else if (Game1.currentLocation is ShopLocation location) { Item clone = item.getOne(); clone.Stack = item.Stack; if (buybackItem != null) { shop.buyBackItemsToResellTomorrow[buybackItem] = clone; } location.itemsToStartSellingTomorrow.Add(clone); } } if (AnimationsField.GetValue(shop) is List <TemporaryAnimatedSprite> animations) { Vector2 animationPosition = shop.inventory.snapToClickableComponent(Game1.getMouseX(), Game1.getMouseY()) + new Vector2(32f, 32f); Vector2 animationMotionTarget = new Vector2(shop.xPositionOnScreen - 36, shop.yPositionOnScreen + shop.height - shop.inventory.height - 16); int coins = item.Stack / 8 + 2; for (int i = 0; i < coins; i++) { animations.Add(new TemporaryAnimatedSprite("TileSheets\\debris", new Rectangle(Game1.random.Next(2) * 16, 64, 16, 16), 9999f, 1, 999, animationPosition, false, false) { scale = 2f, alphaFade = 0.025f, delayBeforeAnimationStart = i * 25, motion = new Vector2(Game1.random.Next(-3, 4), -4f), acceleration = new Vector2(0, 0.5f) }); animations.Add(new TemporaryAnimatedSprite("TileSheets\\debris", new Rectangle(Game1.random.Next(2) * 16, 64, 16, 16), 9999f, 1, 999, animationPosition, false, false) { scale = 4f, alphaFade = 0.025f, delayBeforeAnimationStart = i * 25, motion = Utility.getVelocityTowardPoint(animationPosition, animationMotionTarget, 8f), acceleration = Utility.getVelocityTowardPoint(animationPosition, animationMotionTarget, 0.5f) }); } if (shop.inventory.getItemAt(Game1.getMouseX(), Game1.getMouseY()) == null) { animations.Add(new TemporaryAnimatedSprite(5, animationPosition, Color.White) { motion = new Vector2(0, -0.5f) }); } } Game1.playSound("sell"); Game1.playSound("purchase"); } return(exit); }; }
/// Callback answer for dialogue choice on upgrade menu. private void CallAnswer(Farmer who, string answer) { bool buySuccess = false; if (answer.Equals("Leave")) { return; } else if (answer.Equals("Storage")) { int[] prices = { 2000, 5000, 10000, 20000, 30000, 50000 }; if (ShopMenu.getPlayerCurrencyAmount(Game1.player, 0) >= prices[this.upgradeStorage]) { ShopMenu.chargePlayer(Game1.player, 0, prices[this.upgradeStorage]); this.upgradeStorage++; Game1.drawObjectDialogue("Thank you very much! Your upgrade will be installed by tomorrow."); return; } } else if (answer.Equals("ID")) { Game1.drawObjectDialogue("We cannot provide you with this service at the moment."); return; } else if (answer.Equals("Lim")) { if (ShopMenu.getPlayerCurrencyAmount(Game1.player, 0) >= 10000) { ShopMenu.chargePlayer(Game1.player, 0, 10000); this.upgradeModules += upgradeLim; buySuccess = true; } } else if (answer.Equals("Warp")) { if (ShopMenu.getPlayerCurrencyAmount(Game1.player, 0) >= 20000) { ShopMenu.chargePlayer(Game1.player, 0, 20000); this.upgradeModules += upgradeWarp; buySuccess = true; } } else if (answer.Equals("Portal")) { if (ShopMenu.getPlayerCurrencyAmount(Game1.player, 0) >= 50000) { ShopMenu.chargePlayer(Game1.player, 0, 50000); this.upgradeModules += upgradePortal; buySuccess = true; } } else if (answer.Equals("Dimension")) { if (ShopMenu.getPlayerCurrencyAmount(Game1.player, 0) >= 150000) { ShopMenu.chargePlayer(Game1.player, 0, 150000); this.upgradeModules += upgradeDimension; buySuccess = true; } } if (buySuccess) { Game1.drawObjectDialogue("Thank you very much! Your upgrade module should be active now."); } else { Game1.drawObjectDialogue("It seem like you dont have enough money..."); } }
private void doGridLayoutRightClick(ButtonPressedEventArgs e) { var forSale = Helper.Reflection.GetField <List <ISalable> >(shop, "forSale").GetValue(); var itemPriceAndStock = Helper.Reflection.GetField <Dictionary <ISalable, int[]> >(shop, "itemPriceAndStock").GetValue(); var currency = Helper.Reflection.GetField <int>(shop, "currency").GetValue(); var animations = Helper.Reflection.GetField <List <TemporaryAnimatedSprite> >(shop, "animations").GetValue(); var poof = Helper.Reflection.GetField <TemporaryAnimatedSprite>(shop, "poof").GetValue(); var heldItem = Helper.Reflection.GetField <ISalable>(shop, "heldItem").GetValue(); var currentItemIndex = Helper.Reflection.GetField <int>(shop, "currentItemIndex").GetValue(); var sellPercentage = Helper.Reflection.GetField <float>(shop, "sellPercentage").GetValue(); const int UNIT_WIDTH = 160; const int UNIT_HEIGHT = 144; int unitsWide = (shop.width - 32) / UNIT_WIDTH; int x = (int)e.Cursor.ScreenPixels.X; int y = (int)e.Cursor.ScreenPixels.Y; if (shop.upperRightCloseButton.containsPoint(x, y)) { shop.exitThisMenu(true); return; } // Copying a lot from right click code Vector2 clickableComponent = shop.inventory.snapToClickableComponent(x, y); if (heldItem == null) { Item obj = shop.inventory.rightClick(x, y, null, false); if (obj != null) { if (shop.onSell != null) { shop.onSell(obj); } else { ShopMenu.chargePlayer(Game1.player, currency, -((obj is StardewValley.Object ? (int)((double)(obj as StardewValley.Object).sellToStorePrice() * (double)sellPercentage) : (int)((double)(obj.salePrice() / 2) * (double)sellPercentage)) * obj.Stack)); Item obj2 = (Item)null; if (Game1.mouseClickPolling > 300) { Game1.playSound("purchaseRepeat"); } else { Game1.playSound("purchaseClick"); } animations.Add(new TemporaryAnimatedSprite("TileSheets\\debris", new Rectangle(Game1.random.Next(2) * 64, 256, 64, 64), 9999f, 1, 999, clickableComponent + new Vector2(32f, 32f), false, false) { alphaFade = 0.025f, motion = Utility.getVelocityTowardPoint(new Point((int)clickableComponent.X + 32, (int)clickableComponent.Y + 32), Game1.dayTimeMoneyBox.position + new Vector2(96f, 196f), 12f), acceleration = Utility.getVelocityTowardPoint(new Point((int)clickableComponent.X + 32, (int)clickableComponent.Y + 32), Game1.dayTimeMoneyBox.position + new Vector2(96f, 196f), 0.5f) }); if (obj is StardewValley.Object && (obj as StardewValley.Object).Edibility != -300) { (Game1.getLocationFromName("SeedShop") as StardewValley.Locations.SeedShop).itemsToStartSellingTomorrow.Add(obj.getOne()); } if (shop.inventory.getItemAt(x, y) == null) { Game1.playSound("sell"); animations.Add(new TemporaryAnimatedSprite(5, clickableComponent + new Vector2(32f, 32f), Color.White, 8, false, 100f, 0, -1, -1f, -1, 0) { motion = new Vector2(0.0f, -0.5f) }); } } } } else { heldItem = shop.inventory.leftClick(x, y, (Item)heldItem, true); Helper.Reflection.GetField <ISalable>(shop, "heldItem").SetValue(heldItem); } for (int i = currentItemIndex * unitsWide; i < forSale.Count && i < currentItemIndex * unitsWide + unitsWide * 3; ++i) { int ix = i % unitsWide; int iy = i / unitsWide; Rectangle rect = new Rectangle(shop.xPositionOnScreen + 16 + ix * UNIT_WIDTH, shop.yPositionOnScreen + 16 + iy * UNIT_HEIGHT - currentItemIndex * UNIT_HEIGHT, UNIT_WIDTH, UNIT_HEIGHT); if (rect.Contains(x, y) && forSale[i] != null) { int index2 = i; if (forSale[index2] == null) { break; } int numberToBuy = Game1.oldKBState.IsKeyDown(Keys.LeftShift) ? Math.Min(Math.Min(5, ShopMenu.getPlayerCurrencyAmount(Game1.player, currency) / itemPriceAndStock[forSale[index2]][0]), itemPriceAndStock[forSale[index2]][1]) : 1; var tryToPurchaseItem = Helper.Reflection.GetMethod(shop, "tryToPurchaseItem"); if (numberToBuy > 0 && tryToPurchaseItem.Invoke <bool>(forSale[index2], heldItem, numberToBuy, x, y, index2)) { itemPriceAndStock.Remove(forSale[index2]); forSale.RemoveAt(index2); } if (heldItem == null || !Game1.options.SnappyMenus || (Game1.activeClickableMenu == null || !(Game1.activeClickableMenu is ShopMenu)) || !Game1.player.addItemToInventoryBool((Item)heldItem, false)) { break; } heldItem = (Item)null; Helper.Reflection.GetField <ISalable>(shop, "heldItem").SetValue(heldItem); DelayedAction.playSoundAfterDelay("coin", 100, (GameLocation)null); break; } } }
private void doGridLayoutLeftClick(ButtonPressedEventArgs e) { var forSale = Helper.Reflection.GetField <List <ISalable> >(shop, "forSale").GetValue(); var itemPriceAndStock = Helper.Reflection.GetField <Dictionary <ISalable, int[]> >(shop, "itemPriceAndStock").GetValue(); var currency = Helper.Reflection.GetField <int>(shop, "currency").GetValue(); var animations = Helper.Reflection.GetField <List <TemporaryAnimatedSprite> >(shop, "animations").GetValue(); var poof = Helper.Reflection.GetField <TemporaryAnimatedSprite>(shop, "poof").GetValue(); var heldItem = Helper.Reflection.GetField <ISalable>(shop, "heldItem").GetValue(); var currentItemIndex = Helper.Reflection.GetField <int>(shop, "currentItemIndex").GetValue(); var sellPercentage = Helper.Reflection.GetField <float>(shop, "sellPercentage").GetValue(); var scrollBar = Helper.Reflection.GetField <ClickableTextureComponent>(shop, "scrollBar").GetValue(); var scrollBarRunner = Helper.Reflection.GetField <Rectangle>(shop, "scrollBarRunner").GetValue(); var downArrow = Helper.Reflection.GetField <ClickableTextureComponent>(shop, "downArrow").GetValue(); var upArrow = Helper.Reflection.GetField <ClickableTextureComponent>(shop, "upArrow").GetValue(); const int UNIT_WIDTH = 160; const int UNIT_HEIGHT = 144; int unitsWide = (shop.width - 32) / UNIT_WIDTH; int x = (int)e.Cursor.ScreenPixels.X; int y = (int)e.Cursor.ScreenPixels.Y; if (shop.upperRightCloseButton.containsPoint(x, y)) { shop.exitThisMenu(true); return; } // Copying a lot from left click code if (downArrow.containsPoint(x, y) && currentItemIndex < Math.Max(0, forSale.Count - 18)) { downArrow.scale = downArrow.baseScale; Helper.Reflection.GetField <int>(shop, "currentItemIndex").SetValue(currentItemIndex += 1); if (forSale.Count > 0) { scrollBar.bounds.Y = scrollBarRunner.Height / Math.Max(1, (forSale.Count / 6) - 1 + 1) * currentItemIndex + upArrow.bounds.Bottom + 4; if (currentItemIndex == forSale.Count / 6 - 1) { scrollBar.bounds.Y = downArrow.bounds.Y - scrollBar.bounds.Height - 4; } } Game1.playSound("shwip"); } else if (upArrow.containsPoint(x, y) && currentItemIndex > 0) { upArrow.scale = upArrow.baseScale; Helper.Reflection.GetField <int>(shop, "currentItemIndex").SetValue(currentItemIndex -= 1); if (forSale.Count > 0) { scrollBar.bounds.Y = scrollBarRunner.Height / Math.Max(1, (forSale.Count / 6) - 1 + 1) * currentItemIndex + upArrow.bounds.Bottom + 4; if (currentItemIndex == forSale.Count / 6 - 1) { scrollBar.bounds.Y = downArrow.bounds.Y - scrollBar.bounds.Height - 4; } } Game1.playSound("shwip"); } else if (scrollBarRunner.Contains(x, y)) { int y1 = scrollBar.bounds.Y; scrollBar.bounds.Y = Math.Min(shop.yPositionOnScreen + shop.height - 64 - 12 - scrollBar.bounds.Height, Math.Max(y, shop.yPositionOnScreen + upArrow.bounds.Height + 20)); currentItemIndex = Math.Min(forSale.Count / 6 - 1, Math.Max(0, (int)((double)forSale.Count / 6 * (double)((float)(y - scrollBarRunner.Y) / (float)scrollBarRunner.Height)))); Helper.Reflection.GetField <int>(shop, "currentItemIndex").SetValue(currentItemIndex); if (forSale.Count > 0) { scrollBar.bounds.Y = scrollBarRunner.Height / Math.Max(1, (forSale.Count / 6) - 1 + 1) * currentItemIndex + upArrow.bounds.Bottom + 4; if (currentItemIndex == forSale.Count / 6 - 1) { scrollBar.bounds.Y = downArrow.bounds.Y - scrollBar.bounds.Height - 4; } } int y2 = scrollBar.bounds.Y; if (y1 == y2) { return; } Game1.playSound("shiny4"); } Vector2 clickableComponent = shop.inventory.snapToClickableComponent(x, y); if (heldItem == null) { Item obj = shop.inventory.leftClick(x, y, null, false); if (obj != null) { if (shop.onSell != null) { shop.onSell(obj); } else { ShopMenu.chargePlayer(Game1.player, currency, -((obj is StardewValley.Object ? (int)((double)(obj as StardewValley.Object).sellToStorePrice() * (double)sellPercentage) : (int)((double)(obj.salePrice() / 2) * (double)sellPercentage)) * obj.Stack)); int num = obj.Stack / 8 + 2; for (int index = 0; index < num; ++index) { animations.Add(new TemporaryAnimatedSprite("TileSheets\\debris", new Rectangle(Game1.random.Next(2) * 16, 64, 16, 16), 9999f, 1, 999, clickableComponent + new Vector2(32f, 32f), false, false) { alphaFade = 0.025f, motion = new Vector2((float)Game1.random.Next(-3, 4), -4f), acceleration = new Vector2(0.0f, 0.5f), delayBeforeAnimationStart = index * 25, scale = 2f }); animations.Add(new TemporaryAnimatedSprite("TileSheets\\debris", new Rectangle(Game1.random.Next(2) * 16, 64, 16, 16), 9999f, 1, 999, clickableComponent + new Vector2(32f, 32f), false, false) { scale = 4f, alphaFade = 0.025f, delayBeforeAnimationStart = index * 50, motion = Utility.getVelocityTowardPoint(new Point((int)clickableComponent.X + 32, (int)clickableComponent.Y + 32), new Vector2((float)(shop.xPositionOnScreen - 36), (float)(shop.yPositionOnScreen + shop.height - shop.inventory.height - 16)), 8f), acceleration = Utility.getVelocityTowardPoint(new Point((int)clickableComponent.X + 32, (int)clickableComponent.Y + 32), new Vector2((float)(shop.xPositionOnScreen - 36), (float)(shop.yPositionOnScreen + shop.height - shop.inventory.height - 16)), 0.5f) }); } if (obj is StardewValley.Object && (obj as StardewValley.Object).Edibility != -300) { Item one = obj.getOne(); one.Stack = obj.Stack; (Game1.getLocationFromName("SeedShop") as StardewValley.Locations.SeedShop).itemsToStartSellingTomorrow.Add(one); } Game1.playSound("sell"); Game1.playSound("purchase"); } } } else { heldItem = shop.inventory.leftClick(x, y, (Item)heldItem, true); Helper.Reflection.GetField <ISalable>(shop, "heldItem").SetValue(heldItem); } for (int i = currentItemIndex * unitsWide; i < forSale.Count && i < currentItemIndex * unitsWide + unitsWide * 3; ++i) { int ix = i % unitsWide; int iy = i / unitsWide; Rectangle rect = new Rectangle(shop.xPositionOnScreen + 16 + ix * UNIT_WIDTH, shop.yPositionOnScreen + 16 + iy * UNIT_HEIGHT - currentItemIndex * UNIT_HEIGHT, UNIT_WIDTH, UNIT_HEIGHT); if (rect.Contains(x, y) && forSale[i] != null) { int numberToBuy = Math.Min(Game1.oldKBState.IsKeyDown(Keys.LeftShift) ? Math.Min(Math.Min(5, ShopMenu.getPlayerCurrencyAmount(Game1.player, currency) / Math.Max(1, itemPriceAndStock[forSale[i]][0])), Math.Max(1, itemPriceAndStock[forSale[i]][1])) : 1, forSale[i].maximumStackSize()); if (numberToBuy == -1) { numberToBuy = 1; } var tryToPurchaseItem = Helper.Reflection.GetMethod(shop, "tryToPurchaseItem"); if (numberToBuy > 0 && tryToPurchaseItem.Invoke <bool>(forSale[i], heldItem, numberToBuy, x, y, i)) { itemPriceAndStock.Remove(forSale[i]); forSale.RemoveAt(i); } else if (numberToBuy <= 0) { Game1.dayTimeMoneyBox.moneyShakeTimer = 1000; Game1.playSound("cancel"); } if (heldItem != null && Game1.options.SnappyMenus && (Game1.activeClickableMenu != null && Game1.activeClickableMenu is ShopMenu) && Game1.player.addItemToInventoryBool((Item)heldItem, false)) { heldItem = (Item)null; Helper.Reflection.GetField <ISalable>(shop, "heldItem").SetValue(heldItem); DelayedAction.playSoundAfterDelay("coin", 100, (GameLocation)null); } } } }
public static bool mailbox() { try { if (!DataLoader.ModConfig.DisableQuestService && Game1.player.mailbox.Count == 0 && Game1.player.ActiveObject != null) { foreach (Quest quest in Game1.player.questLog) { if (quest is ItemDeliveryQuest itemDeliveryQuest && !itemDeliveryQuest.completed.Value) { var item = Game1.player.ActiveObject; if ((item.ParentSheetIndex == itemDeliveryQuest.item.Value || item.Category == itemDeliveryQuest.item.Value)) { NPC npc = Game1.getCharacterFromName(itemDeliveryQuest.target.Value); if (item.Stack >= itemDeliveryQuest.number.Value) { if (Game1.player.Money >= DataLoader.ModConfig.QuestServiceFee) { ShopMenu.chargePlayer(Game1.player, 0, DataLoader.ModConfig.QuestServiceFee); Game1.player.ActiveObject.Stack -= (int)itemDeliveryQuest.number.Value - 1; if (DataLoader.ModConfig.ShowDialogOnItemDelivery) { itemDeliveryQuest.reloadDescription(); npc.CurrentDialogue.Push(new Dialogue(itemDeliveryQuest.targetMessage, npc)); Game1.drawDialogue(npc); } Game1.player.reduceActiveItemByOne(); if ((bool)itemDeliveryQuest.dailyQuest.Value) { Game1.player.changeFriendship(150, npc); if (itemDeliveryQuest.deliveryItem.Value == null) { itemDeliveryQuest.deliveryItem.Value = new SObject(Vector2.Zero, itemDeliveryQuest.item.Value, 1); } itemDeliveryQuest.moneyReward.Value = itemDeliveryQuest.deliveryItem.Value.Price * 3; } else { Game1.player.changeFriendship(255, npc); } itemDeliveryQuest.questComplete(); } else { Game1.drawObjectDialogue(DataLoader.I18N.Get("Shipment.Quest.ItemDelivery.NoMoney")); } } else { if (DataLoader.ModConfig.ShowDialogOnItemDelivery) { npc.CurrentDialogue.Push(new Dialogue(Game1.content.LoadString("Strings\\StringsFromCSFiles:ItemDeliveryQuest.cs.13615", itemDeliveryQuest.number.Value), npc)); Game1.drawDialogue(npc); } else { Game1.drawObjectDialogue(DataLoader.I18N.Get("Shipment.Quest.ItemDelivery.NotEnoughItems", new { Npc = npc.displayName, Number = itemDeliveryQuest.number.Value })); } } return(false); } } else if (quest is LostItemQuest lostItemQuest && !lostItemQuest.completed.Value) { if (lostItemQuest.itemFound.Value && Game1.player.hasItemInInventory(lostItemQuest.itemIndex.Value, 1)) { lostItemQuest.questComplete(); NPC npc = Game1.getCharacterFromName(lostItemQuest.npcName.Value); if (DataLoader.ModConfig.ShowDialogOnItemDelivery) { Dictionary <int, string> questData = Game1.temporaryContent.Load <Dictionary <int, string> >("Data\\Quests"); string thankYou = (questData[lostItemQuest.id.Value].Length > 9) ? questData[lostItemQuest.id.Value].Split('/')[9] : Game1.content.LoadString("Data\\ExtraDialogue:LostItemQuest_DefaultThankYou"); npc.setNewDialogue(thankYou); Game1.drawDialogue(npc); } Game1.player.changeFriendship(250, npc); Game1.player.removeFirstOfThisItemFromInventory(lostItemQuest.itemIndex.Value); return(false); } } } }