private void Start() { current = this; EventManager.Instance.AddEventListener <int>("UpdateScrap", UpdateScrapText); backgroundWidth = background.rect.width; buttonWidth = buttonToClone.GetComponent <RectTransform>().rect.width; howManyPerLine = Mathf.Floor(backgroundWidth / (buttonWidth + spacing)); xPos = yPos = spacing; DisplayHulls(); UpdateLights(); GameManager.current.Clear(); }
/// <summary>Raised after the game state is updated (≈60 times per second).</summary> /// <param name="sender">The event sender.</param> /// <param name="e">The event arguments.</param> private void onUpdateTicked(object sender, UpdateTickedEventArgs e) { if (Game1.activeClickableMenu != null) { if ( Game1.activeClickableMenu is CraftingPage ) { CraftingPage menu = Game1.activeClickableMenu as CraftingPage; bool cooking = ( bool ) Util.GetInstanceField( typeof( CraftingPage), Game1.activeClickableMenu, "cooking" ); bool standaloneMenu = ( bool ) Util.GetInstanceField( typeof( CraftingPage), Game1.activeClickableMenu, "_standaloneMenu"); List<Chest> containers = ( List<Chest> ) Util.GetInstanceField( typeof( CraftingPage), Game1.activeClickableMenu, "_materialContainers"); NewCraftingPage myCraftingPage = new NewCraftingPage(menu.xPositionOnScreen, menu.yPositionOnScreen, menu.width, menu.height, cooking, standaloneMenu, containers); myCraftingPage.exitFunction = Game1.activeClickableMenu.exitFunction; Game1.activeClickableMenu = myCraftingPage; } } }
private static bool CraftingPage_clickCraftingRecipe_Prefix(CraftingPage __instance, ClickableTextureComponent c, int ___currentCraftingPage) { if (!Config.EnableMod || !Config.IntRollCraftingChance) { return(true); } if (Game1.random.Next(20) >= GetStatValue(Game1.player, "int")) { __instance.pagesOfCraftingRecipes[___currentCraftingPage][c].createItem(); SMonitor.Log("Int check failed on craft"); Game1.addHUDMessage(new HUDMessage(SHelper.Translation.Get("int-check-failed"), 3)); Game1.playSound("cancel"); return(false); } return(true); }
public static bool IsCooking(this CraftingPage menu) { InitFields(menu.GetType()); if (cookingField == null) { return(false); } object?result = cookingField.GetValue(menu); if (result is bool br) { return(br); } return(false); }
public static bool ClickCraftingRecipe(CraftingPage __instance, ref ClickableTextureComponent c) { CraftingRecipe craftingRecipe = DataLoader.Helper.Reflection.GetField <List <Dictionary <ClickableTextureComponent, CraftingRecipe> > >(__instance, "pagesOfCraftingRecipes").GetValue()[DataLoader.Helper.Reflection.GetField <int>(__instance, "currentCraftingPage").GetValue()][c]; BaitTackle?baitTackle = BaitTackleExtension.GetFromDescription(craftingRecipe.name); if (baitTackle.HasValue) { foreach (Quest quest in Game1.player.questLog.Where(q => q.questType.Value == 1 && q.questTitle == craftingRecipe.name)) { quest.currentObjective = DataLoader.I18N.Get("Quest.LastObjective", new { Item = craftingRecipe.DisplayName }); Game1.addHUDMessage(new HUDMessage(Game1.content.LoadString("Strings\\StringsFromCSFiles:Quest.cs.13636"), 2)); } } return(true); }
/// <summary> /// Fixes the cooking recipe values if they were changed /// </summary> private static void FixCookingRecipeHoverText(CraftingPage craftingMenu) { if (!(bool)GetInstanceField(craftingMenu, "cooking")) { return; } List <Dictionary <ClickableTextureComponent, CraftingRecipe> > pagesOfCraftingRecipes = (List <Dictionary <ClickableTextureComponent, CraftingRecipe> >)GetInstanceField(craftingMenu, "pagesOfCraftingRecipes"); foreach (Dictionary <ClickableTextureComponent, CraftingRecipe> page in pagesOfCraftingRecipes) { foreach (ClickableTextureComponent key in page.Keys) { CraftingRecipe recipe = page[key]; FixFishDish(recipe); FixCropDish(recipe); } } }
private void MenuEvents_MenuChanged(object sender, EventArgsClickableMenuChanged e) { if (Game1.activeClickableMenu is GameMenu) { GameMenu activeMenu = (GameMenu)Game1.activeClickableMenu; List <IClickableMenu> gameMenuPages = Helper.Reflection.GetPrivateField <List <IClickableMenu> >(activeMenu, "pages").GetValue(); foreach (IClickableMenu menu in gameMenuPages) { if (menu is CraftingPage) { List <ClickableTextureComponent> replaceComponents = new List <ClickableTextureComponent>(); CraftingPage craftingPage = (CraftingPage)menu; List <Dictionary <ClickableTextureComponent, CraftingRecipe> > pagesOfCraftingRecipes = craftingPage.pagesOfCraftingRecipes; foreach (Dictionary <ClickableTextureComponent, CraftingRecipe> dict in pagesOfCraftingRecipes) { foreach (ClickableTextureComponent ctc in dict.Keys) { if (ctc.sourceRect.X < 0 || ctc.sourceRect.Y < 0) { ctc.name = dict[ctc].name; replaceComponents.Add(ctc); } } } for (int c = 0; c < replaceComponents.Count; c++) { if (machinesForCrafting.ContainsKey(replaceComponents[c].name)) { replaceComponents[c].texture = machinesForCrafting[replaceComponents[c].name].Texture; replaceComponents[c].sourceRect = machinesForCrafting[replaceComponents[c].name].sourceRectangle; } } } } Helper.Reflection.GetPrivateField <List <IClickableMenu> >(Game1.activeClickableMenu, "pages").SetValue(gameMenuPages); } }
/// <summary> /// Reduces the cost of the crab pot - intended to be used if the player has the Tapper profession /// </summary> /// <param name="gameMenu">The game menu that needs its cost adjusted</param> private static void ReduceCrabPotCost(GameMenu gameMenu) { CraftingPage craftingPage = (CraftingPage)gameMenu.pages[GameMenu.craftingTab]; List <Dictionary <ClickableTextureComponent, CraftingRecipe> > pagesOfCraftingRecipes = (List <Dictionary <ClickableTextureComponent, CraftingRecipe> >)GetInstanceField(craftingPage, "pagesOfCraftingRecipes"); foreach (Dictionary <ClickableTextureComponent, CraftingRecipe> page in pagesOfCraftingRecipes) { foreach (ClickableTextureComponent key in page.Keys) { CraftingRecipe recipe = page[key]; if (recipe.name == "Crab Pot") { CraftableItem crabPot = (CraftableItem)ItemList.Items[(int)ObjectIndexes.CrabPot]; Dictionary <int, int> randomizedRecipe = crabPot.LastRecipeGenerated; ReduceRecipeCost(page[key], randomizedRecipe); } } } }
private void GraphicsEvents_OnPostRenderGuiEvent(object sender, EventArgs e) { GameMenu gm = null; if ((gm = (Game1.activeClickableMenu as GameMenu)) != null && gm.currentTab == 4) { CraftingPage cpage = (CraftingPage)Helper.Reflection .GetPrivateField <List <IClickableMenu> >(gm, "pages").GetValue()[4]; CraftingRecipe cr = Helper.Reflection .GetPrivateField <CraftingRecipe>(cpage, "hoverRecipe").GetValue(); Point p = Game1.getMousePosition(); if (cpage != null && cr != null) { DrawHoverTextBox(Game1.smallFont, "Number crafted: " + Game1.player.craftingRecipes[cr.name], p.X + 31, p.Y - 30); } } }
public void handleOpenCraftingPage(CraftingPage craftingPage) { List <Dictionary <ClickableTextureComponent, CraftingRecipe> > pagesOfCraftingRecipes = ((List <Dictionary <ClickableTextureComponent, CraftingRecipe> >) typeof(CraftingPage).GetField("pagesOfCraftingRecipes", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(craftingPage)); int num = craftingPage.xPositionOnScreen + IClickableMenu.spaceToClearSideBorder + IClickableMenu.borderWidth - Game1.tileSize / 4; int num2 = craftingPage.yPositionOnScreen + IClickableMenu.spaceToClearTopBorder + IClickableMenu.borderWidth - Game1.tileSize / 4; int num3 = 8; int num4 = 10; int num5 = pagesOfCraftingRecipes.Last().Count; if (num5 % 40 == 0) { num5++; } int num7 = num5 / num4 % (40 / num4); Rectangle CTCRect = new Rectangle(num + num5 % num4 * (Game1.tileSize + num3), num2 + num7 * (Game1.tileSize + 8), Game1.tileSize, Game1.tileSize * 2); Rectangle sourceRect = Game1.getSourceRectForStandardTileSheet(Game1.bigCraftableSpriteSheet, 130, 16, 32); pagesOfCraftingRecipes.Last().Add(new ClickableTextureComponent(CTCRect, "", "", Game1.bigCraftableSpriteSheet, sourceRect, Game1.pixelZoom), new TeleChestCraftingRecipe()); PlayerEvents.InventoryChanged += onInventoryChanged; }
private void menuChanged(object sender, EventArgsClickableMenuChanged args) { if (args.NewMenu == null) { return; } if (args.NewMenu is GameMenu gameMenu) { var pages = (List <IClickableMenu>)Helper.Reflection.GetField <List <IClickableMenu> >(gameMenu, "pages").GetValue(); var oldInv = pages[GameMenu.inventoryTab]; if (oldInv.GetType() == typeof(InventoryPage)) { pages[GameMenu.inventoryTab] = new NewInventoryPage( oldInv.xPositionOnScreen, oldInv.yPositionOnScreen, oldInv.width, oldInv.height); } var craftingTab = pages[GameMenu.craftingTab]; if (craftingTab.GetType() == typeof(CraftingPage)) { CraftingPage page = (CraftingPage)pages[GameMenu.craftingTab]; if (page.inventory.rows == 3) { page.inventory = FixInventory(page.inventory); } } } else if (args.NewMenu is MenuWithInventory menuWithInv) { menuWithInv.inventory = FixInventory(menuWithInv.inventory); } else if (args.NewMenu is ShopMenu shop) { shop.inventory = FixInventory(shop.inventory); } else if (args.NewMenu is DialogueBox) { GameEvents.UpdateTick += watchSelectedResponse; } }
public static void Serialize_CraftingPage(dynamic menu, CraftingPage page, Point mousePosition) { int currentCraftingPageIndex = (int)Utils.GetPrivateField(page, "currentCraftingPage"); var recipePage = page.pagesOfCraftingRecipes[currentCraftingPageIndex]; var currentRecipePage = new List <List <dynamic> >(); foreach (var pair in recipePage) { var r = pair.Value; var cmp = Utils.SerializeClickableCmp(pair.Key, mousePosition); var recipe = new { r.name, r.description, itemType = r.ItemType }; currentRecipePage.Add(new List <dynamic> { cmp, recipe }); } menu.menuType = "craftingPage"; menu.currentCraftingPageIndex = currentCraftingPageIndex; menu.downArrow = page.downButton; menu.currentRecipePage = currentRecipePage; menu.inventory = page.inventory; menu.trashCan = page.trashCan; menu.upArrow = page.upButton; }
private static void CraftingPage_Prefix(CraftingPage __instance, int x, int y, bool cooking, List <Chest> material_containers, ref int height) { isCookingMenu = false; containers = null; ingredientMenu = null; if (cooking) { height += 172; containers = material_containers; ingredientMenu = new InventoryMenu(x + IClickableMenu.spaceToClearSideBorder + IClickableMenu.borderWidth, y + IClickableMenu.spaceToClearTopBorder + IClickableMenu.borderWidth + Config.YOffset + 84, false, ingredients, null, 11, 1, 0, 0, true); isCookingMenu = true; cookButton = new ClickableTextureComponent(new Rectangle(x + IClickableMenu.spaceToClearSideBorder + IClickableMenu.borderWidth + 64 * 11, y + IClickableMenu.spaceToClearTopBorder + IClickableMenu.borderWidth + Config.YOffset + 80, 64, 64), Game1.mouseCursors, Game1.getSourceRectForStandardTileSheet(Game1.mouseCursors, 46, -1, -1), 1f, false) { myID = 102, rightNeighborID = -99998, leftNeighborID = 106 }; int labelWidth = (int)Game1.smallFont.MeasureString(SHelper.Translation.Get("fridge-x")).X; fridgeLeftButton = new ClickableTextureComponent("FridgeLeft", new Rectangle(x + IClickableMenu.spaceToClearSideBorder + IClickableMenu.borderWidth - 8, y + IClickableMenu.spaceToClearTopBorder + IClickableMenu.borderWidth + Config.YOffset - 36, 64, 64), null, "", Game1.mouseCursors, Game1.getSourceRectForStandardTileSheet(Game1.mouseCursors, 44, -1, -1), 1f, false) { myID = 631, upNeighborID = -99998, leftNeighborID = -99998, rightNeighborID = -99998, downNeighborID = -99998 }; fridgeRightButton = new ClickableTextureComponent("FridgeRight", new Rectangle(x + IClickableMenu.spaceToClearSideBorder + IClickableMenu.borderWidth + 128 + labelWidth, y + IClickableMenu.spaceToClearTopBorder + IClickableMenu.borderWidth + Config.YOffset - 36, 64, 64), null, "", Game1.mouseCursors, Game1.getSourceRectForStandardTileSheet(Game1.mouseCursors, 33, -1, -1), 1f, false) { myID = 632, upNeighborID = -99998, leftNeighborID = -99998, rightNeighborID = -99998, downNeighborID = -99998 }; } }
private void AddSparklesToCraftingPage(CraftingPage craftingPage, SpriteBatch spriteBatch) { // TODO: a better "new" might be in Cursors.png at around 144 / 440 Texture2D sourceImage = this.Helper.Content.Load <Texture2D>(MOD_SPARKLE, ContentSource.ModFolder); // the following adds stuff to CraftingPage.draw(SpriteBatch) const float scale = Game1.pixelZoom; int offsetX = -sourceImage.Width / 2; int offsetY = -sourceImage.Height / 2; foreach (ClickableComponent component in craftingPage.currentPageClickableComponents) { if (component is ClickableTextureComponent clickableComponent) { Rectangle targetRect = new Rectangle(clickableComponent.bounds.X + offsetX, clickableComponent.bounds.Y + offsetY, (int)(sourceImage.Width * scale), (int)(sourceImage.Height * scale)); // TODO: check periodically if we can access craftingPage.pagesOfCraftingRecipes yet List <Dictionary <ClickableTextureComponent, CraftingRecipe> > pagesOfCraftingRecipes = this.helper.Reflection.GetField <List <Dictionary <ClickableTextureComponent, CraftingRecipe> > >(craftingPage, "pagesOfCraftingRecipes").GetValue(); var craftingRecipe = pagesOfCraftingRecipes.Find((dict) => dict.ContainsKey(clickableComponent)); if (craftingRecipe != null && craftingRecipe[clickableComponent].timesCrafted <= 0) { bool mealWasNotCooked = (craftingRecipe[clickableComponent].isCookingRecipe && !Game1.player.recipesCooked.ContainsKey(craftingRecipe[clickableComponent].getIndexOfMenuView())); bool craftWasNotCrafted = (!craftingRecipe[clickableComponent].isCookingRecipe && craftingRecipe[clickableComponent].timesCrafted <= 0); if (mealWasNotCooked || craftWasNotCrafted) { // FIXME: we want to draw BELOW the popups spriteBatch.Draw(sourceImage, targetRect, null, Color.White, 0, new Vector2(0, 0), SpriteEffects.None, 0); } } } } }
private void update(object sender, EventArgs args) { if (Game1.isEating != wasEating) { if (!Game1.isEating) { // Apparently this happens when the ask to eat dialog opens, but they pressed no. // So make sure something was actually consumed. if (prevToEatStack != -1 && (prevToEatStack - 1 == Game1.player.itemToEat.Stack)) { Object obj = Game1.player.itemToEat as Object; string[] info = Game1.objectInformation[obj.ParentSheetIndex].Split('/'); string[] buffData = ((Convert.ToInt32(info[2]) > 0 && info.Count() > 7) ? info[7].Split(' ') : null); if (buffData != null) { bool allZero = true; foreach (string bd in buffData) { allZero = (allZero && bd == "0"); } if (allZero) { buffData = null; } } if (info[3] == "Cooking -7") { // Need to make sure this is the original buff first. // So it doesn't get rebuffed from eating a buff food -> non buff food -> buff food or something Buff oldBuff = (info[6] == "drink" ? Game1.buffsDisplay.drink : Game1.buffsDisplay.food); Buff thisBuff = null; if (info[6] == "drink") { thisBuff = buffData == null ? null : new Buff(Convert.ToInt32(buffData[0]), Convert.ToInt32(buffData[1]), Convert.ToInt32(buffData[2]), Convert.ToInt32(buffData[3]), Convert.ToInt32(buffData[4]), Convert.ToInt32(buffData[5]), Convert.ToInt32(buffData[6]), Convert.ToInt32(buffData[7]), Convert.ToInt32(buffData[8]), Convert.ToInt32(buffData[9]), Convert.ToInt32(buffData[10]), (buffData.Length > 10) ? Convert.ToInt32(buffData[10]) : 0, (info.Count <string>() > 8) ? Convert.ToInt32(info[8]) : -1, info[0], info[4]); } else { thisBuff = buffData == null ? null : new Buff(Convert.ToInt32(buffData[0]), Convert.ToInt32(buffData[1]), Convert.ToInt32(buffData[2]), Convert.ToInt32(buffData[3]), Convert.ToInt32(buffData[4]), Convert.ToInt32(buffData[5]), Convert.ToInt32(buffData[6]), Convert.ToInt32(buffData[7]), Convert.ToInt32(buffData[8]), Convert.ToInt32(buffData[9]), Convert.ToInt32(buffData[10]), (buffData.Length > 11) ? Convert.ToInt32(buffData[11]) : 0, (info.Count <string>() > 8) ? Convert.ToInt32(info[8]) : -1, info[0], info[4]); } int[] oldAttr = (oldBuff == null ? null : ((int[])Util.GetInstanceField(typeof(Buff), oldBuff, "buffAttributes"))); int[] thisAttr = (thisBuff == null ? null : ((int[])Util.GetInstanceField(typeof(Buff), thisBuff, "buffAttributes"))); Log.trace("Ate something: " + obj + " " + Game1.objectInformation[obj.ParentSheetIndex] + " " + buffData + " " + oldBuff + " " + thisBuff + " " + oldAttr + " " + thisAttr); if (oldBuff != null && thisBuff != null && Enumerable.SequenceEqual(oldAttr, thisAttr) && ((info[6] == "drink" && oldBuff != lastDrink) || (info[6] != "drink" && oldBuff != lastDrink))) { // Now that we know that this is the original buff, we can buff the buff. Log.trace("Buffing buff"); int[] newAttr = (int[])thisAttr.Clone(); if (Game1.player.professions.Contains(PROFESSION_BUFFLEVEL)) { for (int i = 0; i < thisAttr.Length; ++i) { if (newAttr[i] <= 0) { continue; } if (i == 7 || i == 8) { newAttr[i] = (int)(newAttr[i] * 1.2); } else { newAttr[i]++; } } } int newTime = (info.Count <string>() > 8) ? Convert.ToInt32(info[8]) : -1; if (newTime != -1 && Game1.player.professions.Contains(PROFESSION_BUFFTIME)) { newTime = (int)(newTime * 1.25); } Buff newBuff = new Buff(newAttr[0], newAttr[1], newAttr[2], newAttr[3], newAttr[4], newAttr[5], newAttr[6], newAttr[7], newAttr[8], newAttr[9], newAttr[10], newAttr[11], newTime, info[0], info[4]); newBuff.millisecondsDuration = newTime / 10 * 7000; // ^ The vanilla code decreases the duration based on the time of day. // This is fine normally, since it ends as the day ends. // However if you have something like TimeSpeed it just means it won't // last as long later if eaten later in the day. if (info[6] == "drink") { Game1.buffsDisplay.drink.removeBuff(); Game1.buffsDisplay.drink = newBuff; Game1.buffsDisplay.drink.addBuff(); lastDrink = newBuff; } else { Game1.buffsDisplay.food.removeBuff(); Game1.buffsDisplay.food = newBuff; Game1.buffsDisplay.food.addBuff(); lastFood = newBuff; } Game1.buffsDisplay.syncIcons(); } else if (thisBuff == null && Game1.player.professions.Contains(PROFESSION_BUFFPLAIN)) { Log.trace("Buffing plain"); Random rand = new Random(); int[] newAttr = new int[12]; int count = 1 + Math.Min(obj.edibility / 30, 3); for (int i = 0; i < count; ++i) { int attr = rand.Next(10); if (attr >= 3) { ++attr; // 3 unused? } if (attr >= 6) { ++attr; // 6 is crafting speed, unused? } int amt = 1; if (attr == 7 || attr == 8) { amt = 25 + rand.Next(4) * 5; } else { // 36% (assuming I used this probability calculator right) chance for a buff to be level 2 // 4% chance for it to be 3 if (rand.NextDouble() < 0.2) { ++amt; } if (rand.NextDouble() < 0.2) { ++amt; } } newAttr[attr] += amt; } int newTime = 120 + obj.edibility / 10 * 30; Buff newBuff = new Buff(newAttr[0], newAttr[1], newAttr[2], newAttr[3], newAttr[4], newAttr[5], newAttr[6], newAttr[7], newAttr[8], newAttr[9], newAttr[10], newAttr[11], newTime, info[0], info[4]); newBuff.millisecondsDuration = newTime / 10 * 7000; if (info[6] == "drink") { if (Game1.buffsDisplay.drink != null) { Game1.buffsDisplay.drink.removeBuff(); } Game1.buffsDisplay.drink = newBuff; Game1.buffsDisplay.drink.addBuff(); lastDrink = newBuff; } else { if (Game1.buffsDisplay.food != null) { Game1.buffsDisplay.drink.removeBuff(); } Game1.buffsDisplay.drink = newBuff; Game1.buffsDisplay.drink.addBuff(); lastFood = newBuff; } Game1.buffsDisplay.syncIcons(); } } } } Log.trace("Eating:" + Game1.isEating); Log.trace("prev:" + prevToEatStack); Log.trace("I:" + Game1.player.itemToEat + " " + ((Game1.player.itemToEat != null) ? Game1.player.itemToEat.getStack() : -1)); Log.trace("A:" + Game1.player.ActiveObject + " " + ((Game1.player.ActiveObject != null) ? Game1.player.ActiveObject.getStack() : -1)); prevToEatStack = (Game1.player.itemToEat != null ? Game1.player.itemToEat.Stack : -1); } wasEating = Game1.isEating; if (Game1.activeClickableMenu != null) { if (Game1.activeClickableMenu is CraftingPage) { CraftingPage menu = Game1.activeClickableMenu as CraftingPage; bool cooking = ( bool )Util.GetInstanceField(typeof(CraftingPage), Game1.activeClickableMenu, "cooking"); Game1.activeClickableMenu = new NewCraftingPage(menu.xPositionOnScreen, menu.yPositionOnScreen, menu.width, menu.height, cooking); } } }
/// <summary>Initializes extra data for the Crafting Page so it can search for and use materials within bags in your inventory.</summary> private static void OnCraftingPageActivated(CraftingPage CraftingMenu) { // Allow the CraftingPage to search for and use items inside of bags bool AllowUsingBundleBagItemsForCrafting = false; List <ItemBag> BagsInInventory = Game1.player.Items.Where(x => x != null && x is ItemBag).Cast <ItemBag>().ToList(); if (BagsInInventory.Any()) { BagsInUse = new HashSet <ItemBag>(BagsInInventory); // Get the "_materialContainers" protected field that defines additional item containers to search for when using up materials during crafting IReflectedField <List <Chest> > ReflectionResult = Helper.Reflection.GetField <List <Chest> >(CraftingMenu, "_materialContainers", true); List <Chest> MaterialContainers = ReflectionResult.GetValue(); if (MaterialContainers == null) { MaterialContainers = new List <Chest>(); ReflectionResult.SetValue(MaterialContainers); } // Create a temporary chest from the items of each bag, and add the chest to _materialContainers foreach (ItemBag IB in BagsInInventory.Where(x => AllowUsingBundleBagItemsForCrafting || !(x is BundleBag))) { // Note that if the item inside the bag has Stack > 999, it must be split up into chunks with Stacks <= 999 // Because the Game truncates the actual stack down to 999 anytime it modifies a stack value if (IB is OmniBag OB) { foreach (ItemBag NestedBag in OB.NestedBags.Where(x => AllowUsingBundleBagItemsForCrafting || !(x is BundleBag))) { List <Item> TemporaryChestContents = new List <Item>(); foreach (Object Item in NestedBag.Contents) { if (Item.Stack > 999) { if (SplitStacks == null) { SplitStacks = new Dictionary <Object, List <Object> >(); } List <Object> Chunks = new List <Object>(); int TotalStack = Item.Stack; int DistributedAmt = 0; while (DistributedAmt < TotalStack) { int CurrentStackAmt = Math.Min(999, TotalStack - DistributedAmt); Object Chunk = ItemBag.CreateCopy(Item); ItemBag.ForceSetQuantity(Chunk, CurrentStackAmt); DistributedAmt += CurrentStackAmt; Chunks.Add(Chunk); } SplitStacks.Add(Item, Chunks); TemporaryChestContents.AddRange(Chunks); } else { TemporaryChestContents.Add(Item); } } Chest TempChest = new Chest(0, TemporaryChestContents, Vector2.Zero, false, 0); MaterialContainers.Add(TempChest); } } else { List <Item> TemporaryChestContents = new List <Item>(); foreach (Object Item in IB.Contents) { if (Item.Stack > 999) { if (SplitStacks == null) { SplitStacks = new Dictionary <Object, List <Object> >(); } List <Object> Chunks = new List <Object>(); int TotalStack = Item.Stack; int DistributedAmt = 0; while (DistributedAmt < TotalStack) { int CurrentStackAmt = Math.Min(999, TotalStack - DistributedAmt); Object Chunk = ItemBag.CreateCopy(Item); ItemBag.ForceSetQuantity(Chunk, CurrentStackAmt); DistributedAmt += CurrentStackAmt; Chunks.Add(Chunk); } SplitStacks.Add(Item, Chunks); TemporaryChestContents.AddRange(Chunks); } else { TemporaryChestContents.Add(Item); } } Chest TempChest = new Chest(0, TemporaryChestContents, Vector2.Zero, false, 0); MaterialContainers.Add(TempChest); } } } }
/// <summary> /// Unique crafting behaviours for when the Cooking Menu is disabled. /// </summary> public static void CraftItem_Postfix(CraftingPage __instance, Item ___lastCookingHover, ClickableTextureComponent c) { // Do nothing if the Cooking Menu is enabled if (ModEntry.Config.AddCookingMenu) { return; } if (Game1.stats.ItemsCooked <= ModEntry.Instance.States.Value.ItemsCooked) { return; } Item item = ___lastCookingHover; CraftingRecipe recipe = new CraftingRecipe(item.Name, isCookingRecipe: true); // Apply burn chance to destroy cooked food at random /* * if (GameObjects.CookingMenu.GetBurnChance(recipe) > Game1.random.NextDouble()) * { * // Add burnt food to inventory if possible * var burntItem = new StardewValley.Object(Interface.Interfaces.JsonAssets.GetObjectId(ModEntry.ObjectPrefix + "burntfood"), 1); * ModEntry.AddOrDropItem(burntItem); * * // Hunt down the usual food to be incinerated * if (Game1.player.hasItemInInventoryNamed(item.Name)) * { * var items = Game1.player.Items.Where(i => i.Name == item.Name).ToArray(); * var index = Game1.player.Items.IndexOf(items[Game1.random.Next(items.Length)]); * --Game1.player.Items[index].Stack; * if (Game1.player.Items[index].Stack < 1) * Game1.player.removeItemFromInventory(index); * } * else if (Game1.player.isInventoryFull()) * { * var items = Game1.currentLocation.debris.Where(d => d.item.Name == item.Name).ToArray(); * // . . . * } * } */ if (ModEntry.Config.AddCookingSkillAndRecipes) { // TODO: SYSTEM: Finish integrating cooking skill profession bonuses into cooking minus new menu // Apply extra portion bonuses to the amount cooked if (ModEntry.CookingSkillApi.HasProfession(Objects.ICookingSkillAPI.Profession.ExtraPortion) && ModEntry.CookingSkillApi.RollForExtraPortion()) { //qualityStacks[0] += numPerCraft; } // Update tracked stats if (!ModEntry.Instance.States.Value.FoodCookedToday.ContainsKey(item.Name)) { ModEntry.Instance.States.Value.FoodCookedToday[item.Name] = 0; } ModEntry.Instance.States.Value.FoodCookedToday[item.Name] += item.Stack; // Add cooking skill experience ModEntry.CookingSkillApi.CalculateExperienceGainedFromCookingItem( item, numIngredients: recipe.getNumberOfIngredients(), item.Stack, applyExperience: true); } }
/********* ** Private methods *********/ /// <summary>The method to call before <see cref="CraftingPage.clickCraftingRecipe"/>.</summary> /// <returns>Returns whether to run the original method.</returns> /// <remarks>This is copied verbatim from the original method with some changes (marked with comments).</remarks> public static bool Before_ClickCraftingRecipe(CraftingPage __instance, ClickableTextureComponent c, bool playSound, ref int ___currentCraftingPage, ref Item ___heldItem, ref bool ___cooking) { // TODO: // - handle Qi seasoning // - compare with latest game code to see if anything else changed CraftingPage menu = __instance; if (!menu.pagesOfCraftingRecipes[___currentCraftingPage][c].isCookingRecipe) { return(true); } Item crafted = menu.pagesOfCraftingRecipes[___currentCraftingPage][c].createItem(); // custom code begins bool consume = Mod.OnCook(menu.pagesOfCraftingRecipes[___currentCraftingPage][c], crafted, menu._materialContainers); SObject itemObj = crafted as SObject; bool didCraft = false; // custom code ends Game1.player.checkForQuestComplete(null, -1, -1, crafted, null, 2); if (___heldItem == null) { // custom code begins if (consume) { menu.pagesOfCraftingRecipes[___currentCraftingPage][c].consumeIngredients(menu._materialContainers); } didCraft = true; // custom code ends ___heldItem = crafted; if (playSound) { Game1.playSound("coin"); } } else if (___heldItem.Name.Equals(crafted.Name) && ___heldItem.Stack + menu.pagesOfCraftingRecipes[___currentCraftingPage][c].numberProducedPerCraft - 1 < ___heldItem.maximumStackSize()) { ___heldItem.Stack += menu.pagesOfCraftingRecipes[___currentCraftingPage][c].numberProducedPerCraft; // custom code begins if (consume) { menu.pagesOfCraftingRecipes[___currentCraftingPage][c].consumeIngredients(menu._materialContainers); } didCraft = true; // custom code ends if (playSound) { Game1.playSound("coin"); } } // custom code begins if (!didCraft) { return(false); } // custom code ends if (!___cooking && Game1.player.craftingRecipes.ContainsKey(menu.pagesOfCraftingRecipes[___currentCraftingPage][c].name)) { Game1.player.craftingRecipes[menu.pagesOfCraftingRecipes[___currentCraftingPage][c].name] += menu.pagesOfCraftingRecipes[___currentCraftingPage][c].numberProducedPerCraft; } if (___cooking) { Game1.player.cookedRecipe(___heldItem.ParentSheetIndex); // custom code begins Game1.player.AddCustomSkillExperience(Mod.Skill, itemObj.Edibility); // custom code ends } if (!___cooking) { Game1.stats.checkForCraftingAchievements(); } else { Game1.stats.checkForCookingAchievements(); } if (!Game1.options.gamepadControls || ___heldItem == null || !Game1.player.couldInventoryAcceptThisItem(___heldItem)) { return(false); } Game1.player.addItemToInventoryBool(___heldItem); ___heldItem = null; return(false); }
private static void TryCookRecipe(CraftingPage cookingMenu, ref Item heldItem) { SMonitor.Log("Trying to cook recipe"); bool succeeded = false; bool wouldHaveCooked = false; while (true) { bool keepCooking = false; List <string> possible = new List <string>(); foreach (var name in CraftingRecipe.cookingRecipes.Keys) { if (!Config.AllowUnknownRecipes && !Game1.player.cookingRecipes.ContainsKey(name)) { continue; } CraftingRecipe recipe = new CraftingRecipe(name, true); Item crafted = recipe.createItem(); if (crafted == null) { continue; } foreach (var key in recipe.recipeList.Keys) { int need = recipe.recipeList[key]; for (int i = 0; i < ingredients.Count; i++) { if (IsCorrectIngredient(ingredients[i], key)) { int consume = Math.Min(need, ingredients[i].Stack); need -= consume; } if (need <= 0) { break; } } if (need > 0) { goto nextRecipe; } } possible.Add(name); nextRecipe: continue; } possible.Sort(delegate(string a, string b) { return(new CraftingRecipe(b, true).recipeList.Count.CompareTo(new CraftingRecipe(a, true).recipeList.Count)); }); foreach (var name in possible) { CraftingRecipe recipe = new CraftingRecipe(name, true); Item crafted = recipe.createItem(); if (crafted == null) { continue; } if (heldItem is not null && (!heldItem.Name.Equals(crafted.Name) || !heldItem.getOne().canStackWith(crafted.getOne()) || heldItem.Stack + recipe.numberProducedPerCraft - 1 >= heldItem.maximumStackSize())) { if (Config.StoreOtherHeldItemOnCook) { heldItem = Utility.addItemToThisInventoryList(heldItem, cookingMenu.inventory.actualInventory, 36); } if (heldItem != null) { wouldHaveCooked = true; continue; } } SMonitor.Log($"Cooking recipe {name}"); foreach (var key in recipe.recipeList.Keys) { int need = recipe.recipeList[key]; for (int i = 0; i < ingredients.Count; i++) { if (IsCorrectIngredient(ingredients[i], key)) { int consume = Math.Min(need, ingredients[i].Stack); ingredients[i].Stack -= consume; if (ingredients[i].Stack <= 0) { ingredients[i] = null; } need -= consume; } if (need <= 0) { break; } } } bool seasoned = false; for (int i = 0; i < ingredients.Count; i++) { if (ingredients[i]?.ParentSheetIndex == 917) { ingredients[i].Stack--; if (ingredients[i].Stack <= 0) { ingredients[i] = null; } seasoned = true; (crafted as Object).Quality = 2; break; } } Game1.playSound("coin"); if (heldItem == null) { heldItem = crafted; } else { heldItem.Stack += recipe.numberProducedPerCraft; } if (seasoned) { SMonitor.Log("Added seasoning to recipe"); Game1.playSound("breathin"); } Game1.player.checkForQuestComplete(null, -1, -1, crafted, null, 2, -1); Game1.player.cookedRecipe(heldItem.ParentSheetIndex); Game1.stats.checkForCookingAchievements(); if (Game1.options.gamepadControls && heldItem != null && Game1.player.couldInventoryAcceptThisItem(heldItem)) { Game1.player.addItemToInventoryBool(heldItem, false); heldItem = null; } if (Config.LearnUnknownRecipes && !Game1.player.cookingRecipes.ContainsKey(name)) { Game1.player.cookingRecipes.Add(name, 0); Game1.playSound("yoba"); SMonitor.Log("Added new recipe"); Game1.showGlobalMessage(string.Format(SHelper.Translation.Get("new-recipe-x"), name)); AccessTools.Method(typeof(CraftingPage), "layoutRecipes").Invoke(cookingMenu, new object[] { CraftingRecipe.cookingRecipes.Keys.ToList() }); } succeeded = true; if (SHelper.Input.IsDown(Config.CookAllModKey)) { keepCooking = true; } else { UpdateCurrentCookables(); return; } } if (!keepCooking) { break; } } if (succeeded) { if (!SHelper.Input.IsDown(Config.CookAllModKey) && Config.ConsumeExtraIngredientsOnSucceed) { for (int i = 0; i < ingredients.Count; i++) { ingredients[i] = null; } } } else if (wouldHaveCooked) { Game1.addHUDMessage(new HUDMessage(SHelper.Translation.Get("cannot-cook"), 3)); Game1.playSound("cancel"); } else { Game1.addHUDMessage(new HUDMessage(SHelper.Translation.Get("cooking-failed"), 3)); Game1.playSound("cancel"); SMonitor.Log("Failed to cook recipe"); if (!SHelper.Input.IsDown(Config.CookAllModKey)) { if (Config.GiveTrashOnFail || Config.ConsumeIngredientsOnFail) { for (int i = 0; i < ingredients.Count; i++) { ingredients[i] = null; } if (Config.GiveTrashOnFail) { Object trash = new Object(168, 1); if (heldItem == null) { heldItem = trash; } else if (heldItem.Name.Equals(trash.Name) && heldItem.getOne().canStackWith(trash.getOne()) && heldItem.Stack < heldItem.maximumStackSize()) { heldItem.Stack++; } } } } } UpdateCurrentCookables(); }
private void GraphicsEvents_OnPostRenderGuiEvent(object sender, EventArgs e) { if (Game1.activeClickableMenu != null) { Item item = null; if (Game1.activeClickableMenu is GameMenu) { GameMenu menu = (GameMenu)Game1.activeClickableMenu; if (menu.currentTab == 0) { List <IClickableMenu> pages = (List <IClickableMenu>) typeof(GameMenu).GetField("pages", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(menu); InventoryPage inv = (InventoryPage)pages[0]; item = (Item)typeof(InventoryPage).GetField("hoveredItem", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(inv); } if (menu.currentTab == 4) { List <IClickableMenu> pages = (List <IClickableMenu>) typeof(GameMenu).GetField("pages", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(menu); CraftingPage inv = (CraftingPage)pages[4]; item = (Item)typeof(CraftingPage).GetField("hoverItem", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(inv); } } if (Game1.activeClickableMenu is MenuWithInventory) { MenuWithInventory menu = (MenuWithInventory)Game1.activeClickableMenu; InventoryMenu inv = menu.inventory; item = menu.hoveredItem; } if (item == null) { return; } if (item is StardewValley.Object) { StardewValley.Object o = item as StardewValley.Object; if (o.stack > 1) { drawHoverTextBox(Game1.smallFont, o.sellToStorePrice(), o.stack); } else { drawHoverTextBox(Game1.smallFont, o.sellToStorePrice()); } } else if (item != null) { if (item.Stack > 1) { drawHoverTextBox(Game1.smallFont, (item.salePrice() / 2), item.Stack); } else { drawHoverTextBox(Game1.smallFont, item.salePrice()); } } } }
private static bool CraftingPage_layoutRecipes_Prefix(CraftingPage __instance, List <string> playerRecipes) { int craftingPageX = __instance.xPositionOnScreen + IClickableMenu.spaceToClearSideBorder + IClickableMenu.borderWidth - 16; int spaceBetweenCraftingIcons = 8; Dictionary <ClickableTextureComponent, CraftingRecipe> currentPage = Helper.GetHelper().Reflection.GetMethod(__instance, "createNewPage").Invoke <Dictionary <ClickableTextureComponent, CraftingRecipe> >(); int x = 0; int y = 0; int i = 0; ClickableTextureComponent[,] pageLayout = Helper.GetHelper().Reflection.GetMethod(__instance, "createNewPageLayout").Invoke <ClickableTextureComponent[, ]>(); List <ClickableTextureComponent[, ]> pageLayouts = new List <ClickableTextureComponent[, ]>(); pageLayouts.Add(pageLayout); foreach (string playerRecipe in playerRecipes) { i++; CraftingRecipe recipe; if (IsModdedRecipe(playerRecipe)) { recipe = new CustomCraftingRecipe(playerRecipe, false); } else { recipe = new CraftingRecipe(playerRecipe, false); } while (Helper.GetHelper().Reflection.GetMethod(__instance, "spaceOccupied").Invoke <bool>(pageLayout, x, y, recipe)) { x++; if (x >= 10) { x = 0; y++; if (y >= 4) { currentPage = Helper.GetHelper().Reflection.GetMethod(__instance, "createNewPage").Invoke <Dictionary <ClickableTextureComponent, CraftingRecipe> >(); pageLayout = Helper.GetHelper().Reflection.GetMethod(__instance, "createNewPageLayout").Invoke <ClickableTextureComponent[, ]>(); pageLayouts.Add(pageLayout); x = 0; y = 0; } } } int id = 200 + i; ClickableTextureComponent component; if (IsModdedRecipe(playerRecipe)) { recipe = new CustomCraftingRecipe(playerRecipe, false); component = new ClickableTextureComponent ("", new Rectangle(craftingPageX + x * (64 + spaceBetweenCraftingIcons), Helper.GetHelper().Reflection.GetMethod(__instance, "craftingPageY").Invoke <int>() + y * 72, 64, recipe.bigCraftable ? 128 : 64), null, (false && !Game1.player.cookingRecipes.ContainsKey(recipe.name)) ? "ghosted" : "", DataAccess.GetDataAccess().Sprites[Utilities.GetIDName(playerRecipe) + "_Item"], recipe.bigCraftable ? new Rectangle(0, 0, 16, 32) : new Rectangle(0, 0, 16, 16), 4f) { myID = id, rightNeighborID = -99998, leftNeighborID = -99998, upNeighborID = -99998, downNeighborID = -99998, fullyImmutable = true, region = 8000 }; } else { component = new ClickableTextureComponent ("", new Rectangle(craftingPageX + x * (64 + spaceBetweenCraftingIcons), Helper.GetHelper().Reflection.GetMethod(__instance, "craftingPageY").Invoke <int>() + y * 72, 64, recipe.bigCraftable ? 128 : 64), null, (false && !Game1.player.cookingRecipes.ContainsKey(recipe.name)) ? "ghosted" : "", recipe.bigCraftable ? Game1.bigCraftableSpriteSheet : Game1.objectSpriteSheet, recipe.bigCraftable ? Game1.getArbitrarySourceRect(Game1.bigCraftableSpriteSheet, 16, 32, recipe.getIndexOfMenuView()) : Game1.getSourceRectForStandardTileSheet(Game1.objectSpriteSheet, recipe.getIndexOfMenuView(), 16, 16), 4f) { myID = id, rightNeighborID = -99998, leftNeighborID = -99998, upNeighborID = -99998, downNeighborID = -99998, fullyImmutable = true, region = 8000 }; } currentPage.Add(component, recipe); pageLayout[x, y] = component; if (recipe.bigCraftable) { pageLayout[x, y + 1] = component; } } return(false); }