// is this tile and every tile around it plantable?
        private bool BorderClear(Farm farm, Vector2 pos)
        {
            // is this tile in the planting pattern?
            if (!IsTileInPattern(pos))
            {
                return(false);
            }

            if (FruitTree.IsGrowthBlocked(pos, farm))
            {
                //Monitor.Log($"BorderClear [{pos.X}, {pos.Y}]: growth blocked", LogLevel.Warn);
                return(false);
            }

            if (!Plantable(farm, pos))
            {
                //Monitor.Log($"BorderClear [{pos.X}, {pos.Y}]: growth possible but tile not plantable", LogLevel.Warn);
                return(false);
            }

            for (int x = -1; x < 2; x++)
            {
                for (int y = -1; y < 2; y++)
                {
                    Vector2 v = new Vector2(pos.X + x, pos.Y + y);
                    if (!Plantable(farm, v))
                    {
                        //Monitor.Log($"BorderClear [{pos.X}, {pos.Y}]: neighbour tile [{v.X}, {v.Y}] not plantable", LogLevel.Warn);
                        return(false);
                    }
                }
            }
            return(true);
        }
Example #2
0
 /// <summary>Before a save, check every fruit tree to see if it can grow. If not, make it grow.</summary>
 private void OnSaving(object sender, SavingEventArgs e)
 {
     foreach (GameLocation l in Game1.locations)
     {
         foreach (KeyValuePair <Vector2, TerrainFeature> fruitTree in l.terrainFeatures.Pairs.Where(
                      item => item.Value is FruitTree))
         {
             if (FruitTree.IsGrowthBlocked(fruitTree.Key, l))
             {
                 this.SimulateFruitTreeDayUpdate(l, fruitTree.Value as FruitTree);
             }
         }
     }
 }
Example #3
0
 private static bool CanPlantFruitTreeOnTile(GameLocation farm, Vector2 pos)
 {
     if (FruitTree.IsGrowthBlocked(pos, farm))
     {
         return(false);
     }
     if (Util.IsOccupied(farm, pos))
     {
         return(false);
     }
     if (Util.IsHoed(farm, pos))
     {
         return(false);
     }
     return(true);
 }
Example #4
0
        /// <summary>
        /// Grows the fruit tree using the vanilla constraints taken from StardewValley.TerrainFeatures.FruitTree.dayUpdate.
        /// </summary>
        /// <param name="fruittree">current fruit tree</param>
        /// <param name="location">ingame location (e.g. farm)</param>
        /// <param name="tileLocation">position in said location</param>
        /// <param name="increaseGrowthElseRevertGrowth">if true reduce days until mature (grow), otherwise increase days (revert growth)</param>
        private void GrowFruitTree(FruitTree fruittree, GameLocation location, Vector2 tileLocation, bool increaseGrowthElseRevertGrowth)
        {
            bool foundSomething = FruitTree.IsGrowthBlocked(tileLocation, location);

            // check if the tree can grow and if it's not fully matured. the base game reduces daysUntilMatured for fully grown trees to determine the tree age.
            if (!foundSomething && fruittree.growthStage != 4)
            {
                if (increaseGrowthElseRevertGrowth)
                {
                    // grow tree (reduce days until mature)
                    fruittree.daysUntilMature.Set(fruittree.daysUntilMature.Value - 1);
                }
                else
                {
                    // revert tree growth (increase days until mature)
                    fruittree.daysUntilMature.Set(fruittree.daysUntilMature.Value + 1);
                }

                UpdateGrowthStage(fruittree);
            }
        }
        /// <summary>Get the data to display for this subject.</summary>
        /// <remarks>Tree growth algorithm reverse engineered from <see cref="FruitTree.dayUpdate"/>.</remarks>
        public override IEnumerable <ICustomField> GetData()
        {
            FruitTree tree = this.Target;

            // get basic info
            bool isMature            = tree.daysUntilMature.Value <= 0;
            bool isDead              = tree.stump.Value;
            bool isStruckByLightning = tree.struckByLightningCountdown.Value > 0;

            // show next fruit
            if (isMature && !isDead)
            {
                SDate nextFruit = SDate.Now().AddDays(1);

                string label = I18n.FruitTree_NextFruit();
                if (isStruckByLightning)
                {
                    yield return(new GenericField(label, I18n.FruitTree_NextFruit_StruckByLightning(count: tree.struckByLightningCountdown.Value)));
                }
                else if (!this.IsInSeason(tree, nextFruit.Season))
                {
                    yield return(new GenericField(label, I18n.FruitTree_NextFruit_OutOfSeason()));
                }
                else if (tree.fruitsOnTree.Value == FruitTree.maxFruitsOnTrees)
                {
                    yield return(new GenericField(label, I18n.FruitTree_NextFruit_MaxFruit()));
                }
                else
                {
                    yield return(new GenericField(label, I18n.Generic_Tomorrow()));
                }
            }

            // show growth data
            if (!isMature)
            {
                SDate  dayOfMaturity   = SDate.Now().AddDays(tree.daysUntilMature.Value);
                string grownOnDateText = I18n.FruitTree_Growth_Summary(date: this.Stringify(dayOfMaturity));

                yield return(new GenericField(I18n.FruitTree_NextFruit(), I18n.FruitTree_NextFruit_TooYoung()));

                yield return(new GenericField(I18n.FruitTree_Growth(), $"{grownOnDateText} ({this.GetRelativeDateStr(dayOfMaturity)})"));

                if (FruitTree.IsGrowthBlocked(this.Tile, tree.currentLocation))
                {
                    yield return(new GenericField(I18n.FruitTree_Complaints(), I18n.FruitTree_Complaints_AdjacentObjects()));
                }
            }
            else
            {
                // get quality schedule
                ItemQuality currentQuality = this.GetCurrentQuality(tree, this.Constants.FruitTreeQualityGrowthTime);
                if (currentQuality == ItemQuality.Iridium)
                {
                    yield return(new GenericField(I18n.FruitTree_Quality(), I18n.FruitTree_Quality_Now(quality: I18n.For(currentQuality))));
                }
                else
                {
                    string[] summary = this
                                       .GetQualitySchedule(tree, currentQuality, this.Constants.FruitTreeQualityGrowthTime)
                                       .Select(entry =>
                    {
                        // read schedule
                        ItemQuality quality = entry.Key;
                        int daysLeft        = entry.Value;
                        SDate date          = SDate.Now().AddDays(daysLeft);
                        int yearOffset      = date.Year - Game1.year;

                        // generate summary line
                        if (daysLeft <= 0)
                        {
                            return($"-{I18n.FruitTree_Quality_Now(quality: I18n.For(quality))}");
                        }

                        string line = yearOffset == 1
                                ? $"-{I18n.FruitTree_Quality_OnDateNextYear(quality: I18n.For(quality), date: this.Stringify(date))}"
                                : $"-{I18n.FruitTree_Quality_OnDate(quality: I18n.For(quality), date: this.Stringify(date))}";
                        line += $" ({this.GetRelativeDateStr(daysLeft)})";

                        return(line);
                    })
                                       .ToArray();

                    yield return(new GenericField(I18n.FruitTree_Quality(), string.Join(Environment.NewLine, summary)));
                }
            }

            // show season
            yield return(new GenericField(
                             I18n.FruitTree_Season(),
                             I18n.FruitTree_Season_Summary(I18n.GetSeasonName(tree.fruitSeason.Value == "island" ? "summer" : tree.fruitSeason.Value))
                             ));
        }