コード例 #1
0
        /// <summary>
        /// Try find a gift reaction dialogue text for gifted object to an NPC
        /// </summary>
        /// <param name="npc">NPC had recieved a gift</param>
        /// <param name="obj">Gifted item recieved by this NPC</param>
        /// <param name="dialogue">A reaction dialogue text for this gifted item to this NPC</param>
        /// <returns>True if any gift reaction dialogue was found, otherwise false</returns>
        public static bool FetchGiftReaction(NPC npc, SObject obj, out string dialogue, string suffix = "")
        {
            HashSet <string> possibleKeys = new () {
                $"GiftReaction_{obj.Name.Replace(' ', '_')}{suffix}",
                $"GiftReactionCategory_{obj.Category}{suffix}",
                $"GiftReactionPreserved_{obj.preserve.Value}{suffix}",
                $"GiftReactionPreserved_{(obj.preserve.Value.HasValue ? "Any" : "")}{suffix}",
            };

            // Add item context tags as possibly dialogue lines for gift reactions
            possibleKeys.UnionWith(obj.GetContextTags().Select(tag => $"GiftReactionTag_{tag}"));

            foreach (string dialogueKey in possibleKeys)
            {
                if (DialogueHelper.GetRawDialogue(npc.Dialogue, dialogueKey, out KeyValuePair <string, string> reaction))
                {
                    dialogue = reaction.Value;
                    return(true);
                }
            }

            dialogue = "";
            return(false);
        }
コード例 #2
0
        public IEnumerable <SearchableItem> GetAll()
        {
            //
            //
            // Be careful about closure variable capture here!
            //
            // SearchableItem stores the Func<Item> to create new instances later. Loop variables passed into the
            // function will be captured, so every func in the loop will use the value from the last iteration. Use the
            // TryCreate(type, id, entity => item) form to avoid the issue, or create a local variable to pass in.
            //
            //


            IEnumerable <SearchableItem> GetAllRaw()
            {
                // get tools
                for (int q = Tool.stone; q <= Tool.iridium; q++)
                {
                    int quality = q;

                    yield return(this.TryCreate(ItemType.Tool, ToolFactory.axe, _ => ToolFactory.getToolFromDescription(ToolFactory.axe, quality)));

                    yield return(this.TryCreate(ItemType.Tool, ToolFactory.hoe, _ => ToolFactory.getToolFromDescription(ToolFactory.hoe, quality)));

                    yield return(this.TryCreate(ItemType.Tool, ToolFactory.pickAxe, _ => ToolFactory.getToolFromDescription(ToolFactory.pickAxe, quality)));

                    yield return(this.TryCreate(ItemType.Tool, ToolFactory.wateringCan, _ => ToolFactory.getToolFromDescription(ToolFactory.wateringCan, quality)));

                    if (quality != Tool.iridium)
                    {
                        yield return(this.TryCreate(ItemType.Tool, ToolFactory.fishingRod, _ => ToolFactory.getToolFromDescription(ToolFactory.fishingRod, quality)));
                    }
                }
                yield return(this.TryCreate(ItemType.Tool, this.CustomIDOffset, _ => new MilkPail())); // these don't have any sort of ID, so we'll just assign some arbitrary ones

                yield return(this.TryCreate(ItemType.Tool, this.CustomIDOffset + 1, _ => new Shears()));

                yield return(this.TryCreate(ItemType.Tool, this.CustomIDOffset + 2, _ => new Pan()));

                yield return(this.TryCreate(ItemType.Tool, this.CustomIDOffset + 3, _ => new Wand()));

                // clothing
                {
                    // items
                    HashSet <int> clothingIds = new HashSet <int>();
                    foreach (int id in Game1.clothingInformation.Keys)
                    {
                        if (id < 0)
                        {
                            continue; // placeholder data for character customization clothing below
                        }
                        clothingIds.Add(id);
                        yield return(this.TryCreate(ItemType.Clothing, id, p => new Clothing(p.ID)));
                    }

                    // character customization shirts (some shirts in this range have no data, but game has special logic to handle them)
                    for (int id = 1000; id <= 1111; id++)
                    {
                        if (!clothingIds.Contains(id))
                        {
                            yield return(this.TryCreate(ItemType.Clothing, id, p => new Clothing(p.ID)));
                        }
                    }
                }

                // wallpapers
                for (int id = 0; id < 112; id++)
                {
                    yield return(this.TryCreate(ItemType.Wallpaper, id, p => new Wallpaper(p.ID)
                    {
                        Category = SObject.furnitureCategory
                    }));
                }

                // flooring
                for (int id = 0; id < 56; id++)
                {
                    yield return(this.TryCreate(ItemType.Flooring, id, p => new Wallpaper(p.ID, isFloor: true)
                    {
                        Category = SObject.furnitureCategory
                    }));
                }

                // equipment
                foreach (int id in this.TryLoad <int, string>("Data\\Boots").Keys)
                {
                    yield return(this.TryCreate(ItemType.Boots, id, p => new Boots(p.ID)));
                }
                foreach (int id in this.TryLoad <int, string>("Data\\hats").Keys)
                {
                    yield return(this.TryCreate(ItemType.Hat, id, p => new Hat(p.ID)));
                }

                // weapons
                foreach (int id in this.TryLoad <int, string>("Data\\weapons").Keys)
                {
                    yield return(this.TryCreate(ItemType.Weapon, id, p => (p.ID >= 32 && p.ID <= 34)
                        ? (Item) new Slingshot(p.ID)
                        : new MeleeWeapon(p.ID)
                                                ));
                }

                // furniture
                foreach (int id in this.TryLoad <int, string>("Data\\Furniture").Keys)
                {
                    yield return(this.TryCreate(ItemType.Furniture, id, p => Furniture.GetFurnitureInstance(p.ID)));
                }

                // craftables
                foreach (int id in Game1.bigCraftablesInformation.Keys)
                {
                    yield return(this.TryCreate(ItemType.BigCraftable, id, p => new SObject(Vector2.Zero, p.ID)));
                }

                // objects
                foreach (int id in Game1.objectInformation.Keys)
                {
                    string[] fields = Game1.objectInformation[id]?.Split('/');

                    // secret notes
                    if (id == 79)
                    {
                        foreach (int secretNoteId in this.TryLoad <int, string>("Data\\SecretNotes").Keys)
                        {
                            yield return(this.TryCreate(ItemType.Object, this.CustomIDOffset + secretNoteId, _ =>
                            {
                                SObject note = new SObject(79, 1);
                                note.name = $"{note.name} #{secretNoteId}";
                                return note;
                            }));
                        }
                    }

                    // ring
                    else if (id != 801 && fields?.Length >= 4 && fields[3] == "Ring") // 801 = wedding ring, which isn't an equippable ring
                    {
                        yield return(this.TryCreate(ItemType.Ring, id, p => new Ring(p.ID)));
                    }

                    // item
                    else
                    {
                        // spawn main item
                        SObject item = null;
                        yield return(this.TryCreate(ItemType.Object, id, p =>
                        {
                            return item = (p.ID == 812 // roe
                                ? new ColoredObject(p.ID, 1, Color.White)
                                : new SObject(p.ID, 1)
                                           );
                        }));

                        if (item == null)
                        {
                            continue;
                        }

                        // flavored items
                        switch (item.Category)
                        {
                        // fruit products
                        case SObject.FruitsCategory:
                            // wine
                            yield return(this.TryCreate(ItemType.Object, this.CustomIDOffset * 2 + item.ParentSheetIndex, _ => new SObject(348, 1)
                            {
                                Name = $"{item.Name} Wine",
                                Price = item.Price * 3,
                                preserve = { SObject.PreserveType.Wine },
                                preservedParentSheetIndex = { item.ParentSheetIndex }
                            }));

                            // jelly
                            yield return(this.TryCreate(ItemType.Object, this.CustomIDOffset * 3 + item.ParentSheetIndex, _ => new SObject(344, 1)
                            {
                                Name = $"{item.Name} Jelly",
                                Price = 50 + item.Price * 2,
                                preserve = { SObject.PreserveType.Jelly },
                                preservedParentSheetIndex = { item.ParentSheetIndex }
                            }));

                            break;

                        // vegetable products
                        case SObject.VegetableCategory:
                            // juice
                            yield return(this.TryCreate(ItemType.Object, this.CustomIDOffset * 4 + item.ParentSheetIndex, _ => new SObject(350, 1)
                            {
                                Name = $"{item.Name} Juice",
                                Price = (int)(item.Price * 2.25d),
                                preserve = { SObject.PreserveType.Juice },
                                preservedParentSheetIndex = { item.ParentSheetIndex }
                            }));

                            // pickled
                            yield return(this.TryCreate(ItemType.Object, this.CustomIDOffset * 5 + item.ParentSheetIndex, _ => new SObject(342, 1)
                            {
                                Name = $"Pickled {item.Name}",
                                Price = 50 + item.Price * 2,
                                preserve = { SObject.PreserveType.Pickle },
                                preservedParentSheetIndex = { item.ParentSheetIndex }
                            }));

                            break;

                        // flower honey
                        case SObject.flowersCategory:
                            yield return(this.TryCreate(ItemType.Object, this.CustomIDOffset * 5 + item.ParentSheetIndex, _ =>
                            {
                                SObject honey = new SObject(Vector2.Zero, 340, $"{item.Name} Honey", false, true, false, false)
                                {
                                    Name = $"{item.Name} Honey",
                                    preservedParentSheetIndex = { item.ParentSheetIndex }
                                };
                                honey.Price += item.Price * 2;
                                return honey;
                            }));

                            break;

                        // roe and aged roe (derived from FishPond.GetFishProduce)
                        case SObject.sellAtFishShopCategory when item.ParentSheetIndex == 812:
                        {
                            this.GetRoeContextTagLookups(out HashSet <string> simpleTags, out List <List <string> > complexTags);

                            foreach (var pair in Game1.objectInformation)
                            {
                                // get input
                                SObject input     = this.TryCreate(ItemType.Object, pair.Key, p => new SObject(p.ID, 1))?.Item as SObject;
                                var     inputTags = input?.GetContextTags();
                                if (inputTags?.Any() != true)
                                {
                                    continue;
                                }

                                // check if roe-producing fish
                                if (!inputTags.Any(tag => simpleTags.Contains(tag)) && !complexTags.Any(set => set.All(tag => input.HasContextTag(tag))))
                                {
                                    continue;
                                }

                                // yield roe
                                SObject roe   = null;
                                Color   color = this.GetRoeColor(input);
                                yield return(this.TryCreate(ItemType.Object, this.CustomIDOffset * 7 + item.ParentSheetIndex, _ =>
                                    {
                                        roe = new ColoredObject(812, 1, color)
                                        {
                                            name = $"{input.Name} Roe",
                                            preserve = { Value = SObject.PreserveType.Roe },
                                            preservedParentSheetIndex = { Value = input.ParentSheetIndex }
                                        };
                                        roe.Price += input.Price / 2;
                                        return roe;
                                    }));

                                // aged roe
                                if (roe != null && pair.Key != 698)         // aged sturgeon roe is caviar, which is a separate item
                                {
                                    yield return(this.TryCreate(ItemType.Object, this.CustomIDOffset * 7 + item.ParentSheetIndex, _ => new ColoredObject(447, 1, color)
                                        {
                                            name = $"Aged {input.Name} Roe",
                                            Category = -27,
                                            preserve = { Value = SObject.PreserveType.AgedRoe },
                                            preservedParentSheetIndex = { Value = input.ParentSheetIndex },
                                            Price = roe.Price * 2
                                        }));
                                }
                            }
                        }
                        break;
                        }
                    }
                }
            }

            return(GetAllRaw().Where(p => p != null));
        }
コード例 #3
0
        /// <summary>
        /// Check if an input is excluded by a producer rule or a mass production machine definition.
        /// Adapted from https://github.com/Digus/StardewValleyMods/blob/master/ProducerFrameworkMod/ProducerRuleController.cs
        /// </summary>
        /// <param name="producerRule">The producer rule to check.</param>
        /// <param name="mpm">The definition of the mass production machine to check.</param>
        /// <param name="input">The input to check.</param>
        /// <returns>True if it should be excluded.</returns>
        public static bool IsInputExcluded(ProducerRule producerRule, MassProductionMachineDefinition mpm, SObject input)
        {
            bool isExcludedByRule = producerRule.ExcludeIdentifiers != null &&
                                    (producerRule.ExcludeIdentifiers.Contains(input.ParentSheetIndex.ToString()) || producerRule.ExcludeIdentifiers.Contains(input.Name) ||
                                     producerRule.ExcludeIdentifiers.Contains(input.Category.ToString()) || producerRule.ExcludeIdentifiers.Intersect(input.GetContextTags()).Any());
            bool isExcludedByMPM = mpm.BlacklistedInputKeys.Contains(input.ParentSheetIndex.ToString()) || mpm.BlacklistedInputKeys.Contains(input.Name) ||
                                   mpm.BlacklistedInputKeys.Contains(input.Category.ToString()) || mpm.BlacklistedInputKeys.Intersect(input.GetContextTags()).Any();

            return(isExcludedByRule || isExcludedByMPM);
        }
コード例 #4
0
 /// <summary>
 /// Check if an input is excluded by a producer rule.
 /// </summary>
 /// <param name="producerRule">The producer rule to check.</param>
 /// <param name="input">The input to check</param>
 /// <returns>true if should be excluded</returns>
 public static bool IsInputExcluded(ProducerRule producerRule, Object input)
 {
     return(producerRule.ExcludeIdentifiers != null && (producerRule.ExcludeIdentifiers.Contains(input.ParentSheetIndex.ToString()) ||
                                                        producerRule.ExcludeIdentifiers.Contains(input.Name) ||
                                                        producerRule.ExcludeIdentifiers.Contains(input.Category.ToString()) ||
                                                        producerRule.ExcludeIdentifiers.Intersect(input.GetContextTags()).Any()));
 }
コード例 #5
0
        /// <summary>Get flavored variants of a base item (like Blueberry Wine for Blueberry), if any.</summary>
        /// <param name="item">A sample of the base item.</param>
        private IEnumerable <SearchableItem> GetFlavoredObjectVariants(SObject item)
        {
            int id = item.ParentSheetIndex;

            switch (item.Category)
            {
            // fruit products
            case SObject.FruitsCategory:
                // wine
                yield return(this.TryCreate(ItemType.Object, this.CustomIDOffset * 2 + id, _ => new SObject(348, 1)
                {
                    Name = $"{item.Name} Wine",
                    Price = item.Price * 3,
                    preserve = { SObject.PreserveType.Wine },
                    preservedParentSheetIndex = { id }
                }));

                // jelly
                yield return(this.TryCreate(ItemType.Object, this.CustomIDOffset * 3 + id, _ => new SObject(344, 1)
                {
                    Name = $"{item.Name} Jelly",
                    Price = 50 + item.Price * 2,
                    preserve = { SObject.PreserveType.Jelly },
                    preservedParentSheetIndex = { id }
                }));

                break;

            // vegetable products
            case SObject.VegetableCategory:
                // juice
                yield return(this.TryCreate(ItemType.Object, this.CustomIDOffset * 4 + id, _ => new SObject(350, 1)
                {
                    Name = $"{item.Name} Juice",
                    Price = (int)(item.Price * 2.25d),
                    preserve = { SObject.PreserveType.Juice },
                    preservedParentSheetIndex = { id }
                }));

                // pickled
                yield return(this.TryCreate(ItemType.Object, this.CustomIDOffset * 5 + id, _ => new SObject(342, 1)
                {
                    Name = $"Pickled {item.Name}",
                    Price = 50 + item.Price * 2,
                    preserve = { SObject.PreserveType.Pickle },
                    preservedParentSheetIndex = { id }
                }));

                break;

            // flower honey
            case SObject.flowersCategory:
                yield return(this.TryCreate(ItemType.Object, this.CustomIDOffset * 5 + id, _ =>
                {
                    SObject honey = new SObject(Vector2.Zero, 340, $"{item.Name} Honey", false, true, false, false)
                    {
                        Name = $"{item.Name} Honey",
                        preservedParentSheetIndex = { id }
                    };
                    honey.Price += item.Price * 2;
                    return honey;
                }));

                break;

            // roe and aged roe (derived from FishPond.GetFishProduce)
            case SObject.sellAtFishShopCategory when id == 812:
            {
                this.GetRoeContextTagLookups(out HashSet <string> simpleTags, out List <List <string> > complexTags);

                foreach (var pair in Game1.objectInformation)
                {
                    // get input
                    SObject input     = this.TryCreate(ItemType.Object, pair.Key, p => new SObject(p.ID, 1))?.Item as SObject;
                    var     inputTags = input?.GetContextTags();
                    if (inputTags?.Any() != true)
                    {
                        continue;
                    }

                    // check if roe-producing fish
                    if (!inputTags.Any(tag => simpleTags.Contains(tag)) && !complexTags.Any(set => set.All(tag => input.HasContextTag(tag))))
                    {
                        continue;
                    }

                    // yield roe
                    SObject roe   = null;
                    Color   color = this.GetRoeColor(input);
                    yield return(this.TryCreate(ItemType.Object, this.CustomIDOffset * 7 + id, _ =>
                        {
                            roe = new ColoredObject(812, 1, color)
                            {
                                name = $"{input.Name} Roe",
                                preserve = { Value = SObject.PreserveType.Roe },
                                preservedParentSheetIndex = { Value = input.ParentSheetIndex }
                            };
                            roe.Price += input.Price / 2;
                            return roe;
                        }));

                    // aged roe
                    if (roe != null && pair.Key != 698)         // aged sturgeon roe is caviar, which is a separate item
                    {
                        yield return(this.TryCreate(ItemType.Object, this.CustomIDOffset * 7 + id, _ => new ColoredObject(447, 1, color)
                            {
                                name = $"Aged {input.Name} Roe",
                                Category = -27,
                                preserve = { Value = SObject.PreserveType.AgedRoe },
                                preservedParentSheetIndex = { Value = input.ParentSheetIndex },
                                Price = roe.Price * 2
                            }));
                    }
                }
            }
            break;
            }
        }