/// <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))); } }
/// <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))); } }