public void UpdateLocalStockWithSyncedQuanitities(SynchedShop shop, Dictionary <ISalable, int[]> localStock, Dictionary <string, Func <bool> > conditionalItemFilters = null)
        {
            List <Item> itemsToRemove = new List <Item>();
            NetStringDictionary <int, NetInt> sharedStock = getSharedStock(shop);

            if (getLastDayUpdated(shop) != Game1.Date.TotalDays)
            {
                setLastDayUpdated(shop, Game1.Date.TotalDays);
                sharedStock.Clear();
                foreach (Item item5 in localStock.Keys)
                {
                    string itemString3 = Utility.getStandardDescriptionFromItem(item5, 1);
                    sharedStock.Add(itemString3, localStock[item5][1]);
                    if (sharedStock[itemString3] != int.MaxValue)
                    {
                        item5.Stack = sharedStock[itemString3];
                    }
                }
            }
            else
            {
                itemsToRemove.Clear();
                foreach (Item item4 in localStock.Keys)
                {
                    string itemString2 = Utility.getStandardDescriptionFromItem(item4, 1);
                    if (sharedStock.ContainsKey(itemString2) && sharedStock[itemString2] > 0)
                    {
                        localStock[item4][1] = sharedStock[itemString2];
                        if (sharedStock[itemString2] != int.MaxValue)
                        {
                            item4.Stack = sharedStock[itemString2];
                        }
                    }
                    else
                    {
                        itemsToRemove.Add(item4);
                    }
                }
                foreach (Item item3 in itemsToRemove)
                {
                    localStock.Remove(item3);
                }
            }
            itemsToRemove.Clear();
            if (conditionalItemFilters != null)
            {
                foreach (Item item2 in localStock.Keys)
                {
                    string itemString = Utility.getStandardDescriptionFromItem(item2, 1);
                    if (conditionalItemFilters.ContainsKey(itemString) && !conditionalItemFilters[itemString]())
                    {
                        itemsToRemove.Add(item2);
                    }
                }
                foreach (Item item in itemsToRemove)
                {
                    localStock.Remove(item);
                }
            }
        }
示例#2
0
        public void OnItemPurchased(SynchedShop shop, ISalable item, int amount)
        {
            NetStringDictionary <int, NetInt> sharedStock = getSharedStock(shop);
            string itemString = Utility.getStandardDescriptionFromItem(item as Item, 1);

            if (sharedStock.ContainsKey(itemString) && sharedStock[itemString] != int.MaxValue && (!(item is Object) || !(item as Object).IsRecipe))
            {
                sharedStock[itemString] -= amount;
            }
        }
        private void LoadRecipes(IContentPack contentPack, IEnumerable <ContentPackDataInfo> sources)
        {
            var recipes = (from source in sources
                           from entry in source.Content.Recipes
                           select new { Source = source, Data = entry }).ToArray();

            // Create each recipe
            foreach (var recipe in recipes)
            {
                // Create each ingredient
                IRecipePart[] ingredients = recipe.Data.Ingredients.Select(ConvertPart).ToArray();

                // Create each result
                IRecipePart[] results = recipe.Data.Results.Select(ConvertPart).ToArray();

                // Create the recipe
                ISprite sprite     = results.FirstOrDefault()?.Sprite ?? ingredients.FirstOrDefault()?.Sprite ?? throw new InvalidOperationException("Unable to create a sprite for a recipe.");
                string  recipeName = this._api.Items.RegisterCraftingRecipe(new ModRecipe(this._api.TranslationHelper, sprite, results, ingredients, recipe.Data.Name, recipe.Data.IsCooking));

                // TODO: Add conditions when the recipe can be added
                this._api.Owner.Helper.Events.GameLoop.SaveLoaded += (sender, args) => {
                    // Get the target dictionary
                    NetStringDictionary <int, NetInt> targetDictionary = recipe.Data.IsCooking ? Game1.player.craftingRecipes : Game1.player.cookingRecipes;

                    // Add the recipe to the target
                    if (!targetDictionary.ContainsKey(recipeName))
                    {
                        targetDictionary.Add(recipeName, 0);
                    }
                };

                this._api.Owner.Monitor.Log($" - Added recipe: {recipeName}, Ingredients: {ingredients.Length}, Results: {results.Length}", LogLevel.Debug);
            }

            IRecipePart ConvertPart(RecipeData.Part part)
            {
                return(part.Match <RecipeData.Part, IRecipePart>()
                       .When <RecipeData.ModPart>(modPart => {
                    if (!this._api.Items.Delegator.TryParseKey(modPart.Id, out ItemKey key))
                    {
                        key = new ItemKey(contentPack.Manifest, modPart.Id);
                    }

                    return new ModRecipePart(this._api, key, part.Quantity);
                })
                       .When <RecipeData.GamePart>(gamePart => gamePart.Type == RecipeData.ItemType.OBJECT, gamePart => new SObjectRecipePart(this._api, gamePart.Id, gamePart.Quantity))
                       .When <RecipeData.GamePart>(gamePart => gamePart.Type == RecipeData.ItemType.BIGCRAFTABLE, gamePart => new BigCraftableRecipePart(this._api, gamePart.Id, gamePart.Quantity))
                       .When <RecipeData.GamePart>(gamePart => gamePart.Type == RecipeData.ItemType.WEAPON, gamePart => new WeaponRecipePart(this._api, gamePart.Id, gamePart.Quantity))
                       .When <RecipeData.GamePart>(gamePart => gamePart.Type == RecipeData.ItemType.HAT, gamePart => new HatRecipePart(this._api, gamePart.Id, gamePart.Quantity))
                       .ElseThrow(_ => new InvalidOperationException($"Unknown part type: {part.GetType().FullName}")));
            }
        }
示例#4
0
        /// <summary>
        /// Takes a list of recipes and check if the player has learned it from the given list of recipes ( either cooking or crafting )
        /// All spaces in given recipe names should be replaced with `-` because spaces are used as a delimiter (i.e. Seafoam Pudding should be entered as Seafoam-Pudding )
        /// </summary>
        private bool CheckHasRecipe(string[] conditionParams,
                                    NetStringDictionary <int, NetInt> craftingRecipes)
        {
            for (int i = 1; i < conditionParams.Length; i++)
            {
                if (!(from rec in craftingRecipes.Keys
                      select rec.Replace(" ", "-")).Contains(conditionParams[i]))
                {
                    return(false);
                }
            }

            return(true);
        }
示例#5
0
 /// <summary>Allows generic interactions with NPCs in <see cref="MovieTheater"/> under certain conditions.</summary>
 /// <param name="__instance">The <see cref="MovieTheater"/> instance.</param>
 /// <param name="tileLocation">The tile targeted by this action.</param>
 /// <param name="viewport">The viewport of the player performing this action.</param>
 /// <param name="who">The player performing this action.</param>
 /// <param name="____playerInvitedPatrons">The list of NPCs invited by the player. Non-public field for this <see cref="MovieTheater"/> instance.</param>
 /// <param name="____characterGroupLookup">The list of NPC patrons currently present. Non-public field for this <see cref="MovieTheater"/> instance.</param>
 /// <param name="__result">The result of the original method.</param>
 private static void MovieTheater_checkAction(MovieTheater __instance,
                                              Location tileLocation,
                                              xTile.Dimensions.Rectangle viewport,
                                              Farmer who,
                                              NetStringDictionary <int, NetInt> ____playerInvitedPatrons,
                                              NetStringDictionary <bool, NetBool> ____characterGroupLookup,
                                              ref bool __result)
 {
     try
     {
         if (__result == true) //if the original method return true
         {
             PropertyValue action = null;
             __instance.map.GetLayer("Buildings").PickTile(new Location(tileLocation.X * 64, tileLocation.Y * 64), viewport.Size)?.Properties.TryGetValue("Action", out action); //get this tile's Action property if it exists
             if (action == null)                                                                                                                                                 //if this tile does NOT have an Action property
             {
                 Microsoft.Xna.Framework.Rectangle tileRect = new Microsoft.Xna.Framework.Rectangle(tileLocation.X * 64, tileLocation.Y * 64, 64, 64);                           //get this tile's pixel area
                 foreach (NPC npc in __instance.characters)                                                                                                                      //for each NPC in this location
                 {
                     if (npc.isVillager() && npc.GetBoundingBox().Intersects(tileRect))                                                                                          //if this NPC is a villager and targeted by this action
                     {
                         string npcName = npc.Name;
                         if (____playerInvitedPatrons.ContainsKey(npcName) == false && ____characterGroupLookup.ContainsKey(npcName) == false) //if this NPC is NOT here as a patron (i.e. does not have patron-specific dialogue or behavior)
                         {
                             __result = npc.checkAction(who, __instance);                                                                      //check action on this NPC (i.e. talk/give gifts/etc) and override the result
                             return;
                         }
                     }
                 }
             }
         }
     }
     catch (Exception ex)
     {
         Monitor.LogOnce($"Harmony patch \"{nameof(HarmonyPatch_MovieTheaterNPCs)}\" has encountered an error. Postfix \"{nameof(MovieTheater_checkAction)}\" might malfunction or revert to default behavior. Full error message: \n{ex.ToString()}", LogLevel.Error);
         return; //run the original method
     }
 }
        /***
         * Modified from StardewValley.CraftingPage.clickCraftingRecipe
         ***/
        /// <summary>
        /// Crafts the recipe.
        /// </summary>
        /// <param name="recipe">The recipe to craft.</param>
        /// <param name="playSound">If set to <c>true</c> play sound.</param>
        private void CraftRecipe(CraftingRecipe recipe, bool playSound = true)
        {
            List <Ingredient> ingredients = SelectIngredients(recipe);
            int avgQuality       = 0;
            int totalIngredients = 0;

            foreach (Ingredient ingredient in ingredients)
            {
                SObject selectedItem = ingredient.Item as SObject;
                avgQuality       += selectedItem.Quality * selectedItem.Stack;
                totalIngredients += selectedItem.Stack;
            }

            avgQuality /= totalIngredients;
            if (avgQuality == 3)
            {
                avgQuality = 4;
            }

            Util.Monitor.VerboseLog($"Crafting {recipe.DisplayName} (quality {avgQuality})");

            Item item = recipe.createItem();

            if (item is SObject obj)
            {
                obj.Quality = avgQuality;
            }

            Game1.player.checkForQuestComplete(null, -1, -1, item, null, 2, -1);
            if (heldItem == null)
            {
                heldItem = item;

                foreach (Ingredient ingredient in ingredients)
                {
                    ingredient.Consume();
                }

                if (playSound)
                {
                    Game1.playSound("coin");
                }
            }
            else if (heldItem.canStackWith(item) && heldItem.Stack + recipe.numberProducedPerCraft - 1 < heldItem.maximumStackSize())
            {
                heldItem.Stack += recipe.numberProducedPerCraft;

                foreach (Ingredient ingredient in ingredients)
                {
                    ingredient.Consume();
                }

                if (playSound)
                {
                    Game1.playSound("coin");
                }
            }
            if (!cooking && Game1.player.craftingRecipes.ContainsKey(recipe.name))
            {
                NetStringDictionary <int, NetInt> craftingRecipes = Game1.player.craftingRecipes;
                string name = recipe.name;
                craftingRecipes[name] += recipe.numberProducedPerCraft;
            }
            if (cooking)
            {
                Game1.player.cookedRecipe(heldItem.parentSheetIndex);
            }
            if (!cooking)
            {
                Game1.stats.checkForCraftingAchievements();
            }
            else
            {
                Game1.stats.checkForCookingAchievements();
            }
            if (Game1.options.gamepadControls && heldItem != null && Game1.player.couldInventoryAcceptThisItem(heldItem))
            {
                Game1.player.addItemToInventoryBool(heldItem, false);
                heldItem = null;
            }
        }
示例#7
0
        /*
         * Modded method
         */
        private void clickCraftingRecipe(ClickableTextureComponent c, bool playSound = true)
        {
            List <Ingredient> ingredients = SelectIngredients(pagesOfCraftingRecipes[currentCraftingPage][c]);

            int avgQuality       = 0;
            int totalIngredients = 0;

            foreach (Ingredient ingredient in ingredients)
            {
                SObject selectedItem = ingredient.ItemList[ingredient.Index] as SObject;
                avgQuality       += selectedItem.Quality * selectedItem.Stack;
                totalIngredients += selectedItem.Stack;
            }
            avgQuality /= totalIngredients;
            if (avgQuality == 3)
            {
                avgQuality = 4;
            }

            Item item = pagesOfCraftingRecipes[currentCraftingPage][c].createItem();

            if (item is SObject obj)
            {
                obj.Quality = avgQuality;
            }

            Game1.player.checkForQuestComplete(null, -1, -1, item, null, 2, -1);
            if (heldItem == null)
            {
                heldItem = item;

                foreach (Ingredient ingredient in ingredients)
                {
                    Item usedItem = ingredient.ItemList[ingredient.Index];
                    if (usedItem.Stack - ingredient.Amount <= 0)
                    {
                        ingredient.ItemList[ingredient.Index] = null;
                    }
                    else
                    {
                        usedItem.Stack -= ingredient.Amount;
                    }
                }

                if (playSound)
                {
                    Game1.playSound("coin");
                }
            }
            else if (heldItem.canStackWith(item) && heldItem.Stack + pagesOfCraftingRecipes[currentCraftingPage][c].numberProducedPerCraft - 1 < heldItem.maximumStackSize())
            {
                heldItem.Stack += pagesOfCraftingRecipes[currentCraftingPage][c].numberProducedPerCraft;

                foreach (Ingredient ingredient in ingredients)
                {
                    Item usedItem = ingredient.ItemList[ingredient.Index];
                    if (usedItem.Stack - ingredient.Amount <= 0)
                    {
                        ingredient.ItemList[ingredient.Index] = null;
                    }
                    else
                    {
                        usedItem.Stack -= ingredient.Amount;
                    }
                }

                if (playSound)
                {
                    Game1.playSound("coin");
                }
            }
            if (!cooking && Game1.player.craftingRecipes.ContainsKey(pagesOfCraftingRecipes[currentCraftingPage][c].name))
            {
                NetStringDictionary <int, NetInt> craftingRecipes = Game1.player.craftingRecipes;
                string name = pagesOfCraftingRecipes[currentCraftingPage][c].name;
                craftingRecipes[name] += pagesOfCraftingRecipes[currentCraftingPage][c].numberProducedPerCraft;
            }
            if (cooking)
            {
                Game1.player.cookedRecipe(heldItem.parentSheetIndex);
            }
            if (!cooking)
            {
                Game1.stats.checkForCraftingAchievements();
            }
            else
            {
                Game1.stats.checkForCookingAchievements();
            }
            if (Game1.options.gamepadControls && heldItem != null && Game1.player.couldInventoryAcceptThisItem(heldItem))
            {
                Game1.player.addItemToInventoryBool(heldItem, false);
                heldItem = null;
            }
        }