Пример #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;
            Object obj        = item as Object;
            bool   isCrop     = this.FromCrop != null;
            bool   isSeed     = this.SeedForCrop != null;
            bool   isDeadCrop = this.FromCrop?.dead == true;

            // get overrides
            bool showInventoryFields = true;

            {
                ObjectData objData = metadata.GetObject(item, this.Context);
                if (objData != null)
                {
                    this.Name           = objData.Name ?? this.Name;
                    this.Description    = objData.Description ?? this.Description;
                    this.Type           = objData.Type ?? this.Type;
                    showInventoryFields = objData.ShowInventoryFields ?? true;
                }
            }

            // don't show data for dead crop
            if (isDeadCrop)
            {
                yield return(new GenericField("Crop", "This crop is dead."));

                yield break;
            }

            // crop fields
            if (isCrop || isSeed)
            {
                // get crop
                Crop crop = this.FromCrop ?? this.SeedForCrop;

                // get harvest schedule
                int  harvestablePhase   = crop.phaseDays.Count - 1;
                bool canHarvestNow      = (crop.currentPhase >= harvestablePhase) && (!crop.fullyGrown || crop.dayOfCurrentPhase <= 0);
                int  daysToFirstHarvest = crop.phaseDays.Take(crop.phaseDays.Count - 1).Sum(); // ignore harvestable phase

                // add next-harvest field
                if (isCrop)
                {
                    // calculate next harvest
                    int daysToNextHarvest = 0;
                    Tuple <string, int> dayOfNextHarvest = null;
                    if (!canHarvestNow)
                    {
                        // calculate days until next harvest
                        int daysUntilLastPhase = daysToFirstHarvest - crop.dayOfCurrentPhase - crop.phaseDays.Take(crop.currentPhase).Sum();
                        {
                            // growing: days until next harvest
                            if (!crop.fullyGrown)
                            {
                                daysToNextHarvest = daysUntilLastPhase;
                            }

                            // regrowable crop harvested today
                            else if (crop.dayOfCurrentPhase >= crop.regrowAfterHarvest)
                            {
                                daysToNextHarvest = crop.regrowAfterHarvest;
                            }

                            // regrowable crop
                            else
                            {
                                daysToNextHarvest = crop.dayOfCurrentPhase; // dayOfCurrentPhase decreases to 0 when fully grown, where <=0 is harvestable
                            }
                        }
                        dayOfNextHarvest = GameHelper.GetDayOffset(daysToNextHarvest, metadata.Constants.DaysInSeason);
                    }

                    // generate field
                    string summary;
                    if (canHarvestNow)
                    {
                        summary = "now";
                    }
                    else if (Game1.currentLocation.Name != Constant.LocationNames.Greenhouse && !crop.seasonsToGrowIn.Contains(dayOfNextHarvest.Item1))
                    {
                        summary = $"too late in the season for the next harvest (would be on {dayOfNextHarvest.Item1} {dayOfNextHarvest.Item2})";
                    }
                    else
                    {
                        summary = $"{dayOfNextHarvest.Item1} {dayOfNextHarvest.Item2} ({GameHelper.Pluralise(daysToNextHarvest, "tomorrow", $"in {daysToNextHarvest} days")})";
                    }

                    yield return(new GenericField("Harvest", summary));
                }

                // crop summary
                {
                    List <string> summary = new List <string>();

                    // harvest
                    summary.Add($"-harvest after {daysToFirstHarvest} {GameHelper.Pluralise(daysToFirstHarvest, "day")}" + (crop.regrowAfterHarvest != -1 ? $", then every {GameHelper.Pluralise(crop.regrowAfterHarvest, "day", $"{crop.regrowAfterHarvest} days")}" : ""));

                    // seasons
                    summary.Add($"-grows in {string.Join(", ", crop.seasonsToGrowIn)}");

                    // drops
                    if (crop.minHarvest != crop.maxHarvest && crop.chanceForExtraCrops > 0)
                    {
                        summary.Add($"-drops {crop.minHarvest} to {crop.maxHarvest} ({Math.Round(crop.chanceForExtraCrops * 100, 2)}% chance of extra crops)");
                    }
                    else if (crop.minHarvest > 1)
                    {
                        summary.Add($"-drops {crop.minHarvest}");
                    }

                    // crop sale price
                    Item drop = GameHelper.GetObjectBySpriteIndex(crop.indexOfHarvest);
                    summary.Add($"-sells for {SaleValueField.GetSummary(this.GetSaleValue(drop, false), 1)}");

                    // generate field
                    yield return(new GenericField("Crop", string.Join(Environment.NewLine, summary)));
                }
            }

            // crafting
            if (obj?.heldObject != null)
            {
                if (obj is Cask)
                {
                    // get cask data
                    Cask        cask           = (Cask)obj;
                    Object      agingObj       = cask.heldObject;
                    ItemQuality currentQuality = (ItemQuality)agingObj.quality;

                    // calculate aging schedule
                    float effectiveAge = metadata.Constants.CaskAgeSchedule.Values.Max() - cask.daysToMature;
                    var   schedule     =
                        (
                            from entry in metadata.Constants.CaskAgeSchedule
                            let quality = entry.Key
                                          let baseDays = entry.Value
                                                         where baseDays > effectiveAge
                                                         orderby baseDays ascending
                                                         let daysLeft = (int)Math.Ceiling((baseDays - effectiveAge) / cask.agingRate)
                                                                        select new
                    {
                        Quality = quality,
                        DaysLeft = daysLeft,
                        HarvestDate = GameHelper.GetDayOffset(daysLeft, metadata.Constants.DaysInSeason)
                    }
                        )
                        .ToArray();

                    // display fields
                    yield return(new ItemIconField("Contents", obj.heldObject));

                    if (cask.minutesUntilReady <= 0 || !schedule.Any())
                    {
                        yield return(new GenericField("Aging", $"{currentQuality.GetName()} quality ready"));
                    }
                    else
                    {
                        string scheduleStr = string.Join(Environment.NewLine, (from entry in schedule select $"-{entry.Quality.GetName()} {GameHelper.Pluralise(entry.DaysLeft, "tomorrow", $"in {entry.DaysLeft} days")} ({entry.HarvestDate.Item1} {entry.HarvestDate.Item2})"));
                        yield return(new GenericField("Aging", $"-{currentQuality.GetName()} now (use pickaxe to stop aging){Environment.NewLine}" + scheduleStr));
                    }
                }
                else
                {
                    yield return(new ItemIconField("Contents", obj.heldObject, $"{obj.heldObject.Name} " + (obj.minutesUntilReady > 0 ? "in " + GenericField.GetString(TimeSpan.FromMinutes(obj.minutesUntilReady)) : "ready")));
                }
            }

            // item
            if (showInventoryFields)
            {
                var giftTastes = this.GetGiftTastes(item);
                if (!isCrop)
                {
                    yield return(new SaleValueField("Sells for", this.GetSaleValue(item, this.KnownQuality), item.Stack));
                }
                yield return(new ItemGiftTastesField("Loves this", giftTastes, GiftTaste.Love));

                yield return(new ItemGiftTastesField("Likes this", giftTastes, GiftTaste.Like));
            }

            // fence
            if (item is Fence)
            {
                Fence fence = (Fence)item;

                // health
                if (Game1.getFarm().isBuildingConstructed(Constant.BuildingNames.GoldClock))
                {
                    yield return(new GenericField("Health", "no decay with Gold Clock"));
                }
                else
                {
                    float maxHealth = fence.isGate ? fence.maxHealth * 2 : fence.maxHealth;
                    float health    = fence.health / maxHealth;
                    float daysLeft  = fence.health * metadata.Constants.FenceDecayRate / 60 / 24;
                    yield return(new PercentageBarField("Health", (int)fence.health, (int)maxHealth, Color.Green, Color.Red, $"{Math.Round(health * 100)}% (roughly {Math.Round(daysLeft)} days left)"));
                }
            }

            // recipes
            if (obj != null && obj.bigCraftable != true)
            {
                RecipeModel[] recipes = GameHelper.GetRecipesForIngredient(this.DisplayItem).ToArray();
                if (recipes.Any())
                {
                    yield return(new RecipesForIngredientField("Recipes", item, recipes));
                }
            }
        }
Пример #2
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)
        {
            NPC npc = this.Target;

            switch (this.TargetType)
            {
            case TargetType.Villager:
                if (!metadata.Constants.AsocialVillagers.Contains(npc.getName()))
                {
                    var giftTastes = this.GetGiftTastes(npc);

                    yield return(new GenericField("Birthday", $"{Utility.capitalizeFirstLetter(npc.birthday_Season)} {npc.birthday_Day}"));

                    // friendship
                    if (Game1.player.friendships.ContainsKey(npc.name))
                    {
                        FriendshipModel friendship = DataParser.GetFriendshipForVillager(Game1.player, npc, metadata);
                        yield return(new GenericField("Can romance", friendship.IsSpouse ? "you're married! <" : GenericField.GetString(npc.datable)));

                        yield return(new CharacterFriendshipField("Friendship", friendship));

                        yield return(new GenericField("Talked today", Game1.player.friendships[npc.name][2] == 1));

                        yield return(new GenericField("Gifted today", Game1.player.friendships[npc.name][3] > 0));

                        if (!friendship.IsSpouse)
                        {
                            yield return(new GenericField("Gifted this week", $"{Game1.player.friendships[npc.name][1]} of {NPC.maxGiftsPerWeek}"));
                        }
                    }
                    else
                    {
                        yield return(new GenericField("Friendship", "You haven't met them yet."));
                    }
                    yield return(new CharacterGiftTastesField("Loves gifts", giftTastes, GiftTaste.Love));

                    yield return(new CharacterGiftTastesField("Likes gifts", giftTastes, GiftTaste.Like));
                }
                break;

            case TargetType.Pet:
                Pet pet = (Pet)npc;
                yield return(new CharacterFriendshipField("Love", DataParser.GetFriendshipForPet(Game1.player, pet)));

                yield return(new GenericField("Petted today", GameHelper.GetPrivateField <bool>(pet, "wasPetToday")));

                break;

            case TargetType.Monster:
                // basic info
                Monster monster = (Monster)npc;
                yield return(new GenericField("Invincible", $"For {GameHelper.GetPrivateField<int>(monster, "invincibleCountdown")} seconds", hasValue: monster.isInvincible()));

                yield return(new PercentageBarField("Health", monster.health, monster.maxHealth, Color.Green, Color.Gray, $"{Math.Round((monster.health / (monster.maxHealth * 1f) * 100))}% ({monster.health} of {monster.maxHealth})"));

                yield return(new ItemDropListField("Drops", this.GetMonsterDrops(monster), defaultText: "nothing"));

                yield return(new GenericField("XP", monster.experienceGained));

                yield return(new GenericField("Defence", monster.resilience));

                yield return(new GenericField("Attack", monster.damageToFarmer));

                // Adventure Guild quest
                AdventureGuildQuestData adventureGuildQuest = metadata.GetAdventurerGuildQuest(monster.name);
                if (adventureGuildQuest != null)
                {
                    int kills = adventureGuildQuest.Targets.Select(p => Game1.stats.getMonstersKilled(p)).Sum();
                    yield return(new GenericField("Adventure Guild", $"{(kills >= adventureGuildQuest.RequiredKills ? "complete" : "in progress")} (killed {kills} of {adventureGuildQuest.RequiredKills})"));
                }
                break;
            }
        }