Example #1
0
        /// <summary>Get the data to display for this subject.</summary>
        /// <param name="metadata">Provides metadata that's not available from the game data directly.</param>
        public override IEnumerable <ICustomField> GetData(Metadata metadata)
        {
            // get data
            Item    item       = this.Target;
            SObject obj        = item as SObject;
            bool    isCrop     = this.FromCrop != null;
            bool    isSeed     = this.SeedForCrop != null;
            bool    isDeadCrop = this.FromCrop?.dead.Value == true;
            bool    canSell    = obj?.canBeShipped() == true || metadata.Shops.Any(shop => shop.BuysCategories.Contains(item.Category));

            // get overrides
            bool showInventoryFields = true;

            {
                ObjectData objData = metadata.GetObject(item, this.Context);
                if (objData != null)
                {
                    this.Name = objData.NameKey != null?L10n.GetRaw(objData.NameKey) : this.Name;

                    this.Description = objData.DescriptionKey != null?L10n.GetRaw(objData.DescriptionKey) : this.Description;

                    this.Type = objData.TypeKey != null?L10n.GetRaw(objData.TypeKey) : this.Type;

                    showInventoryFields = objData.ShowInventoryFields ?? true;
                }
            }

            // don't show data for dead crop
            if (isDeadCrop)
            {
                yield return(new GenericField(this.GameHelper, L10n.Crop.Summary(), L10n.Crop.SummaryDead()));

                yield break;
            }

            // crop fields
            foreach (ICustomField field in this.GetCropFields(this.FromCrop ?? this.SeedForCrop, isSeed, metadata))
            {
                yield return(field);
            }

            // indoor pot crop
            if (obj is IndoorPot pot)
            {
                Crop potCrop = pot.hoeDirt.Value.crop;
                if (potCrop != null)
                {
                    Item drop = this.GameHelper.GetObjectBySpriteIndex(potCrop.indexOfHarvest.Value);
                    yield return(new LinkField(this.GameHelper, L10n.Item.Contents(), drop.DisplayName, () => new ItemSubject(this.GameHelper, this.Text, this.GameHelper.GetObjectBySpriteIndex(potCrop.indexOfHarvest.Value), ObjectContext.World, knownQuality: false, fromCrop: potCrop)));
                }
            }

            // machine output
            foreach (ICustomField field in this.GetMachineOutputFields(obj, metadata))
            {
                yield return(field);
            }

            // item
            if (showInventoryFields)
            {
                // needed for
                foreach (ICustomField field in this.GetNeededForFields(obj, metadata))
                {
                    yield return(field);
                }

                // sale data
                if (canSell && !isCrop)
                {
                    // sale price
                    string saleValueSummary = GenericField.GetSaleValueString(this.GetSaleValue(item, this.KnownQuality, metadata), item.Stack, this.Text);
                    yield return(new GenericField(this.GameHelper, L10n.Item.SellsFor(), saleValueSummary));

                    // sell to
                    List <string> buyers = new List <string>();
                    if (obj?.canBeShipped() == true)
                    {
                        buyers.Add(L10n.Item.SellsToShippingBox());
                    }
                    buyers.AddRange(
                        from shop in metadata.Shops
                        where shop.BuysCategories.Contains(item.Category)
                        let name = L10n.GetRaw(shop.DisplayKey).ToString()
                                   orderby name
                                   select name
                        );
                    yield return(new GenericField(this.GameHelper, L10n.Item.SellsTo(), string.Join(", ", buyers)));
                }

                // gift tastes
                var giftTastes = this.GetGiftTastes(item, metadata);
                yield return(new ItemGiftTastesField(this.GameHelper, L10n.Item.LovesThis(), giftTastes, GiftTaste.Love));

                yield return(new ItemGiftTastesField(this.GameHelper, L10n.Item.LikesThis(), giftTastes, GiftTaste.Like));
            }

            // fence
            if (item is Fence fence)
            {
                string healthLabel = L10n.Item.FenceHealth();

                // health
                if (Game1.getFarm().isBuildingConstructed(Constant.BuildingNames.GoldClock))
                {
                    yield return(new GenericField(this.GameHelper, healthLabel, L10n.Item.FenceHealthGoldClock()));
                }
                else
                {
                    float  maxHealth = fence.isGate.Value ? fence.maxHealth.Value * 2 : fence.maxHealth.Value;
                    float  health    = fence.health.Value / maxHealth;
                    double daysLeft  = Math.Round(fence.health.Value * metadata.Constants.FenceDecayRate / 60 / 24);
                    double percent   = Math.Round(health * 100);
                    yield return(new PercentageBarField(this.GameHelper, healthLabel, (int)fence.health.Value, (int)maxHealth, Color.Green, Color.Red, L10n.Item.FenceHealthSummary(percent: (int)percent, count: (int)daysLeft)));
                }
            }

            // recipes
            if (item.GetSpriteType() == ItemSpriteType.Object)
            {
                RecipeModel[] recipes = this.GameHelper.GetRecipesForIngredient(this.DisplayItem).ToArray();
                if (recipes.Any())
                {
                    yield return(new RecipesForIngredientField(this.GameHelper, L10n.Item.Recipes(), item, recipes));
                }
            }

            // owned and times cooked/crafted
            if (showInventoryFields && !isCrop && !(item is Tool))
            {
                // owned
                yield return(new GenericField(this.GameHelper, L10n.Item.Owned(), L10n.Item.OwnedSummary(count: this.GameHelper.CountOwnedItems(item))));

                // times crafted
                RecipeModel[] recipes = this.GameHelper
                                        .GetRecipes()
                                        .Where(recipe => recipe.OutputItemIndex == this.Target.ParentSheetIndex)
                                        .ToArray();
                if (recipes.Any())
                {
                    string label        = recipes.First().Type == RecipeType.Cooking ? L10n.Item.Cooked() : L10n.Item.Crafted();
                    int    timesCrafted = recipes.Sum(recipe => recipe.GetTimesCrafted(Game1.player));
                    if (timesCrafted != -1) // -1 == times crafted not available for this recipe type
                    {
                        yield return(new GenericField(this.GameHelper, label, L10n.Item.CraftedSummary(count: timesCrafted)));
                    }
                }
            }

            // see also crop
            bool seeAlsoCrop =
                isSeed &&
                item.ParentSheetIndex != this.SeedForCrop.indexOfHarvest.Value && // skip seeds which produce themselves (e.g. coffee beans)
                !(item.ParentSheetIndex >= 495 && item.ParentSheetIndex <= 497) && // skip random seasonal seeds
                item.ParentSheetIndex != 770;    // skip mixed seeds

            if (seeAlsoCrop)
            {
                Item drop = this.GameHelper.GetObjectBySpriteIndex(this.SeedForCrop.indexOfHarvest.Value);
                yield return(new LinkField(this.GameHelper, L10n.Item.SeeAlso(), drop.DisplayName, () => new ItemSubject(this.GameHelper, this.Text, drop, ObjectContext.Inventory, false, this.SeedForCrop)));
            }
        }
Example #2
0
        /// <summary>Get the data to display for this subject.</summary>
        public override IEnumerable <ICustomField> GetData()
        {
            // get data
            Item    item       = this.Target;
            SObject obj        = item as SObject;
            bool    isCrop     = this.FromCrop != null;
            bool    isSeed     = this.SeedForCrop != null;
            bool    isDeadCrop = this.FromCrop?.dead.Value == true;
            bool    canSell    = obj?.canBeShipped() == true || this.Metadata.Shops.Any(shop => shop.BuysCategories.Contains(item.Category));

            // get overrides
            bool showInventoryFields = true;

            {
                ObjectData objData = this.Metadata.GetObject(item, this.Context);
                if (objData != null)
                {
                    this.Name = objData.NameKey != null?L10n.GetRaw(objData.NameKey) : this.Name;

                    this.Description = objData.DescriptionKey != null?L10n.GetRaw(objData.DescriptionKey) : this.Description;

                    this.Type = objData.TypeKey != null?L10n.GetRaw(objData.TypeKey) : this.Type;

                    showInventoryFields = objData.ShowInventoryFields ?? true;
                }
            }

            // don't show data for dead crop
            if (isDeadCrop)
            {
                yield return(new GenericField(this.GameHelper, L10n.Crop.Summary(), L10n.Crop.SummaryDead()));

                yield break;
            }

            // crop fields
            foreach (ICustomField field in this.GetCropFields(this.FromCrop ?? this.SeedForCrop, isSeed))
            {
                yield return(field);
            }

            // indoor pot crop
            if (obj is IndoorPot pot)
            {
                Crop potCrop = pot.hoeDirt.Value.crop;
                if (potCrop != null)
                {
                    Item drop = this.GameHelper.GetObjectBySpriteIndex(potCrop.indexOfHarvest.Value);
                    yield return(new LinkField(this.GameHelper, L10n.Item.Contents(), drop.DisplayName, () => this.Codex.GetCrop(potCrop, ObjectContext.World)));
                }
            }

            // machine output
            foreach (ICustomField field in this.GetMachineOutputFields(obj))
            {
                yield return(field);
            }

            // item
            if (showInventoryFields)
            {
                // needed for
                foreach (ICustomField field in this.GetNeededForFields(obj))
                {
                    yield return(field);
                }

                // sale data
                if (canSell && !isCrop)
                {
                    // sale price
                    string saleValueSummary = GenericField.GetSaleValueString(this.GetSaleValue(item, this.KnownQuality), item.Stack, this.Text);
                    yield return(new GenericField(this.GameHelper, L10n.Item.SellsFor(), saleValueSummary));

                    // sell to
                    List <string> buyers = new List <string>();
                    if (obj?.canBeShipped() == true)
                    {
                        buyers.Add(L10n.Item.SellsToShippingBox());
                    }
                    buyers.AddRange(
                        from shop in this.Metadata.Shops
                        where shop.BuysCategories.Contains(item.Category)
                        let name = L10n.GetRaw(shop.DisplayKey).ToString()
                                   orderby name
                                   select name
                        );
                    yield return(new GenericField(this.GameHelper, L10n.Item.SellsTo(), string.Join(", ", buyers)));
                }

                // clothing
                if (item is Clothing clothing)
                {
                    yield return(new GenericField(this.GameHelper, L10n.Item.CanBeDyed(), this.Stringify(clothing.dyeable.Value)));
                }

                // gift tastes
                IDictionary <GiftTaste, GiftTasteModel[]> giftTastes = this.GetGiftTastes(item);
                yield return(new ItemGiftTastesField(this.GameHelper, L10n.Item.LovesThis(), giftTastes, GiftTaste.Love, onlyRevealed: this.ProgressionMode, highlightUnrevealed: this.HighlightUnrevealedGiftTastes));

                yield return(new ItemGiftTastesField(this.GameHelper, L10n.Item.LikesThis(), giftTastes, GiftTaste.Like, onlyRevealed: this.ProgressionMode, highlightUnrevealed: this.HighlightUnrevealedGiftTastes));

                if (this.ProgressionMode || this.HighlightUnrevealedGiftTastes)
                {
                    yield return(new ItemGiftTastesField(this.GameHelper, L10n.Item.NeutralAboutThis(), giftTastes, GiftTaste.Neutral, onlyRevealed: this.ProgressionMode, highlightUnrevealed: this.HighlightUnrevealedGiftTastes));

                    yield return(new ItemGiftTastesField(this.GameHelper, L10n.Item.DislikesThis(), giftTastes, GiftTaste.Dislike, onlyRevealed: this.ProgressionMode, highlightUnrevealed: this.HighlightUnrevealedGiftTastes));

                    yield return(new ItemGiftTastesField(this.GameHelper, L10n.Item.HatesThis(), giftTastes, GiftTaste.Hate, onlyRevealed: this.ProgressionMode, highlightUnrevealed: this.HighlightUnrevealedGiftTastes));
                }
            }

            // recipes
            switch (item.GetItemType())
            {
            // for ingredient
            case ItemType.Object:
            {
                RecipeModel[] recipes = this.GameHelper.GetRecipesForIngredient(this.DisplayItem).ToArray();
                if (recipes.Any())
                {
                    yield return(new RecipesForIngredientField(this.GameHelper, L10n.Item.Recipes(), item, recipes));
                }
            }
            break;

            // for machine
            case ItemType.BigCraftable:
            {
                RecipeModel[] recipes = this.GameHelper.GetRecipesForMachine(this.DisplayItem as SObject).ToArray();
                if (recipes.Any())
                {
                    yield return(new RecipesForMachineField(this.GameHelper, L10n.Item.Recipes(), recipes));
                }
            }
            break;
            }

            // fish
            if (item.Category == SObject.FishCategory)
            {
                // spawn rules
                yield return(new FishSpawnRulesField(this.GameHelper, L10n.Item.FishSpawnRules(), item.ParentSheetIndex, this.Text));

                // fish pond data
                foreach (FishPondData fishPondData in Game1.content.Load <List <FishPondData> >("Data\\FishPondData"))
                {
                    if (!fishPondData.RequiredTags.All(item.HasContextTag))
                    {
                        continue;
                    }

                    int    minChanceOfAnyDrop = (int)Math.Round(Utility.Lerp(0.15f, 0.95f, 1 / 10f) * 100);
                    int    maxChanceOfAnyDrop = (int)Math.Round(Utility.Lerp(0.15f, 0.95f, FishPond.MAXIMUM_OCCUPANCY / 10f) * 100);
                    string preface            = L10n.Building.FishPondDropsPreface(chance: L10n.Generic.Range(min: minChanceOfAnyDrop, max: maxChanceOfAnyDrop));
                    yield return(new FishPondDropsField(this.GameHelper, L10n.Item.FishPondDrops(), -1, fishPondData, preface));

                    break;
                }
            }

            // fence
            if (item is Fence fence)
            {
                string healthLabel = L10n.Item.FenceHealth();

                // health
                if (Game1.getFarm().isBuildingConstructed(Constant.BuildingNames.GoldClock))
                {
                    yield return(new GenericField(this.GameHelper, healthLabel, L10n.Item.FenceHealthGoldClock()));
                }
                else
                {
                    float  maxHealth = fence.isGate.Value ? fence.maxHealth.Value * 2 : fence.maxHealth.Value;
                    float  health    = fence.health.Value / maxHealth;
                    double daysLeft  = Math.Round(fence.health.Value * this.Constants.FenceDecayRate / 60 / 24);
                    double percent   = Math.Round(health * 100);
                    yield return(new PercentageBarField(this.GameHelper, healthLabel, (int)fence.health.Value, (int)maxHealth, Color.Green, Color.Red, L10n.Item.FenceHealthSummary(percent: (int)percent, count: (int)daysLeft)));
                }
            }

            // movie ticket
            if (obj?.ParentSheetIndex == 809 && !obj.bigCraftable.Value)
            {
                MovieData movie = MovieTheater.GetMovieForDate(Game1.Date);
                if (movie == null)
                {
                    yield return(new GenericField(this.GameHelper, L10n.MovieTicket.MovieThisWeek(), L10n.MovieTicket.NoMovieThisWeek()));
                }
                else
                {
                    // movie this week
                    yield return(new GenericField(this.GameHelper, L10n.MovieTicket.MovieThisWeek(), new IFormattedText[]
                    {
                        new FormattedText(movie.Title, bold: true),
                        new FormattedText(Environment.NewLine),
                        new FormattedText(movie.Description)
                    }));

                    // movie tastes
                    IDictionary <GiftTaste, string[]> tastes = this.GameHelper.GetMovieTastes()
                                                               .GroupBy(entry => entry.Value)
                                                               .ToDictionary(group => group.Key, group => group.Select(p => p.Key.Name).OrderBy(p => p).ToArray());

                    yield return(new MovieTastesField(this.GameHelper, L10n.MovieTicket.LovesMovie(), tastes, GiftTaste.Love));

                    yield return(new MovieTastesField(this.GameHelper, L10n.MovieTicket.LikesMovie(), tastes, GiftTaste.Like));

                    yield return(new MovieTastesField(this.GameHelper, L10n.MovieTicket.DislikesMovie(), tastes, GiftTaste.Dislike));
                }
            }

            // dyes
            yield return(new ColorField(this.GameHelper, L10n.Item.ProducesDye(), item));

            // owned and times cooked/crafted
            if (showInventoryFields && !isCrop)
            {
                // owned
                yield return(new GenericField(this.GameHelper, L10n.Item.Owned(), L10n.Item.OwnedSummary(count: this.GameHelper.CountOwnedItems(item))));

                // times crafted
                RecipeModel[] recipes = this.GameHelper
                                        .GetRecipes()
                                        .Where(recipe => recipe.OutputItemIndex == this.Target.ParentSheetIndex)
                                        .ToArray();
                if (recipes.Any())
                {
                    string label        = recipes.First().Type == RecipeType.Cooking ? L10n.Item.Cooked() : L10n.Item.Crafted();
                    int    timesCrafted = recipes.Sum(recipe => recipe.GetTimesCrafted(Game1.player));
                    if (timesCrafted >= 0) // negative value means not available for this recipe type
                    {
                        yield return(new GenericField(this.GameHelper, label, L10n.Item.CraftedSummary(count: timesCrafted)));
                    }
                }
            }

            // see also crop
            bool seeAlsoCrop =
                isSeed &&
                item.ParentSheetIndex != this.SeedForCrop.indexOfHarvest.Value && // skip seeds which produce themselves (e.g. coffee beans)
                !(item.ParentSheetIndex >= 495 && item.ParentSheetIndex <= 497) && // skip random seasonal seeds
                item.ParentSheetIndex != 770;    // skip mixed seeds

            if (seeAlsoCrop)
            {
                Item drop = this.GameHelper.GetObjectBySpriteIndex(this.SeedForCrop.indexOfHarvest.Value);
                yield return(new LinkField(this.GameHelper, L10n.Item.SeeAlso(), drop.DisplayName, () => this.Codex.GetCrop(this.SeedForCrop, ObjectContext.Inventory)));
            }
        }