// ReSharper disable once InconsistentNaming
        private static void HandleItemDrop(int itemToDrop, ref FarmAnimal __instance)
        {
            var flag3   = true;
            var quality = ChooseQuality(ref __instance);

            foreach (var @object in __instance.home.indoors.Value.objects.Values
                     .Where(@object =>
                            @object.bigCraftable.Value && @object.ParentSheetIndex == 165 && @object.heldObject.Value != null)
                     .Where(@object => (@object.heldObject.Value as Chest)?
                            .addItem(new Object(Vector2.Zero, itemToDrop, null, false, true,
                                                false, false)
            {
                Quality = quality
            }) == null))
            {
                @object.showNextIndex.Value = true;
                flag3 = false;
                break;
            }

            if (flag3 && !__instance.home.indoors.Value.Objects.ContainsKey(__instance.getTileLocation()))
            {
                StardewValley.Utility.spawnObjectAround(__instance.getTileLocation(),
                                                        new Object(Vector2.Zero, itemToDrop, null, false, true, false, true)
                {
                    Quality = quality
                },
                                                        __instance.home.indoors.Value);
            }
        }
Exemple #2
0
 public static void dayUpdate(FarmAnimal __instance)
 {
     if (__instance.harvestType.Value == FarmAnimal.layHarvestType &&
         __instance.daysSinceLastLay.Value == 0 &&
         AnimalContestController.HasFertilityBonus(__instance) &&
         !DataLoader.ModConfig.DisableContestBonus)
     {
         GameLocation homeIndoors = __instance.home.indoors.Value;
         if (homeIndoors.Objects.ContainsKey(__instance.getTileLocation()))
         {
             StardewValley.Object originalLayedObject = homeIndoors.Objects[__instance.getTileLocation()];
             if (originalLayedObject.Category == StardewValley.Object.EggCategory)
             {
                 __instance.setRandomPosition(homeIndoors);
                 if (!homeIndoors.Objects.ContainsKey(__instance.getTileLocation()))
                 {
                     homeIndoors.Objects.Add(__instance.getTileLocation(), new StardewValley.Object(Vector2.Zero, originalLayedObject.ParentSheetIndex, (string)null, false, true, false, true)
                     {
                         Quality = originalLayedObject.Quality
                     });
                 }
             }
         }
     }
 }
        public static bool FarmAnimalDayUpdate(ref FarmAnimal __instance, GameLocation environtment)
        {
            __instance.controller   = null;
            __instance.health.Value = 3;
            bool flag1 = false;

            if (__instance.home != null && !(__instance.home.indoors.Value as AnimalHouse).animals.ContainsKey(__instance.myID) && environtment is Farm)
            {
                if (!__instance.home.animalDoorOpen.Value)
                {
                    __instance.moodMessage.Value = 6;
                    flag1 = true;
                    __instance.happiness.Value /= 2;
                }
                else
                {
                    (environtment as Farm).animals.Remove(__instance.myID.Value);
                    (__instance.home.indoors.Value as AnimalHouse).animals.Add(__instance.myID.Value, __instance);
                    if (Game1.timeOfDay > 1800 && __instance.controller == null)
                    {
                        __instance.happiness.Value /= 2;
                    }
                    environtment = __instance.home.indoors.Value;
                    __instance.setRandomPosition(environtment);
                    return(false);
                }
            }
            ++__instance.daysSinceLastLay.Value;
            if (!__instance.wasPet.Value)
            {
                __instance.friendshipTowardFarmer.Value = Math.Max(0, __instance.friendshipTowardFarmer.Value - (10 - __instance.friendshipTowardFarmer / 200));
                __instance.happiness.Value = (byte)Math.Max(0, __instance.happiness.Value - __instance.happinessDrain.Value * 5);
            }
            __instance.wasPet.Value = false;
            if ((__instance.fullness.Value < 200 || Game1.timeOfDay < 1700) && environtment is AnimalHouse)
            {
                for (int index = environtment.objects.Count() - 1; index >= 0; --index)
                {
                    KeyValuePair <Vector2, SObject> keyValuePair = environtment.objects.Pairs.ElementAt(index);
                    if (keyValuePair.Value.Name.Equals("Hay"))
                    {
                        OverlaidDictionary objects = environtment.objects;
                        keyValuePair = environtment.objects.Pairs.ElementAt(index);
                        Vector2 key = keyValuePair.Key;
                        objects.Remove(key);
                        __instance.fullness.Value = Byte.MaxValue;
                        break;
                    }
                }
            }
            var random = new Random((int)(long)__instance.myID / 2 + (int)Game1.stats.DaysPlayed);

            if (__instance.fullness > 200 || random.NextDouble() < (__instance.fullness.Value - 30) / 170.0)
            {
                ++__instance.age.Value;
                if (__instance.age.Value == __instance.ageWhenMature.Value)
                {
                    __instance.Sprite.LoadTexture("Animals\\" + __instance.type.Value);
                    if (__instance.type.Value.Contains("Sheep"))
                    {
                        __instance.currentProduce.Value = __instance.defaultProduceIndex;
                    }
                    __instance.daysSinceLastLay.Value = 99;
                }
                __instance.happiness.Value = (byte)Math.Min(Byte.MaxValue, __instance.happiness.Value + __instance.happinessDrain.Value * 2);
            }
            if (__instance.fullness.Value < 200)
            {
                __instance.happiness.Value = (byte)Math.Max(0, __instance.happiness.Value - 100);
                __instance.friendshipTowardFarmer.Value = Math.Max(0, __instance.friendshipTowardFarmer.Value - 20);
            }
            bool flag2 = __instance.daysSinceLastLay.Value >= __instance.daysToLay.Value - (!__instance.type.Value.Equals("Sheep") || !Game1.getFarmer(__instance.ownerID.Value).professions.Contains(3) ? 0 : 1) && random.NextDouble() < __instance.fullness.Value / 200.0 && random.NextDouble() < __instance.happiness.Value / 70.0;
            int  parentSheetIndex;

            if (!flag2 || __instance.age.Value < __instance.ageWhenMature.Value)
            {
                parentSheetIndex = -1;
            }
            else
            {
                __instance.daysSinceLastLay.Value = 0;
                parentSheetIndex = __instance.defaultProduceIndex.Value;
                if (parentSheetIndex == 107 && Loader.CONFIG.InfertileEggs)
                {
                    parentSheetIndex = Loader.DATA["Dino Egg"];
                }
                if (random.NextDouble() < __instance.happiness.Value / 150.0)
                {
                    float num1 = __instance.happiness.Value > 200 ? __instance.happiness.Value * 1.5f : (__instance.happiness.Value <= 100 ? __instance.happiness.Value - 100 : 0.0f);
                    if (__instance.type.Value.Equals("Duck") && random.NextDouble() < (__instance.friendshipTowardFarmer.Value + (double)num1) / 5000.0 + Game1.player.team.AverageDailyLuck(null) + Game1.player.team.AverageLuckLevel(null) * 0.01)
                    {
                        parentSheetIndex = __instance.deluxeProduceIndex.Value;
                    }
                    else if (__instance.type.Value.Equals("Rabbit") && random.NextDouble() < (__instance.friendshipTowardFarmer.Value + (double)num1) / 5000.0 + Game1.player.team.AverageDailyLuck(null) + Game1.player.team.AverageLuckLevel(null) * 0.02)
                    {
                        parentSheetIndex = __instance.deluxeProduceIndex.Value;
                    }
                    else if (__instance.type.Value.Equals("Blue Chicken") && random.NextDouble() < (__instance.friendshipTowardFarmer.Value + (double)num1) / 5000.0 + Game1.player.team.AverageDailyLuck() + Game1.player.team.AverageLuckLevel() * 0.01)
                    {
                        parentSheetIndex = Loader.DATA["Blue Chicken Egg"];
                    }
                    switch (parentSheetIndex)
                    {
                    case 176:
                        ++Game1.stats.ChickenEggsLayed;
                        break;

                    case 180:
                        ++Game1.stats.ChickenEggsLayed;
                        break;

                    case 440:
                        ++Game1.stats.RabbitWoolProduced;
                        break;

                    case 442:
                        ++Game1.stats.DuckEggsLayed;
                        break;
                    }
                    if (random.NextDouble() < (__instance.friendshipTowardFarmer.Value + num1) / 1200.0 && !__instance.type.Value.Equals("Duck") && (!__instance.type.Value.Equals("Rabbit") && !__instance.type.Value.Equals("Blue Chicken") && __instance.deluxeProduceIndex.Value != -1) && __instance.friendshipTowardFarmer.Value >= 200)
                    {
                        parentSheetIndex = __instance.deluxeProduceIndex.Value;
                    }
                    double num2 = __instance.friendshipTowardFarmer.Value / 1000.0 - (1.0 - __instance.happiness.Value / 225.0);
                    if (!__instance.isCoopDweller() && Game1.getFarmer(__instance.ownerID.Value).professions.Contains(3) || __instance.isCoopDweller() && Game1.getFarmer(__instance.ownerID.Value).professions.Contains(2))
                    {
                        num2 += 0.33;
                    }
                    if (num2 >= 0.95 && random.NextDouble() < num2 / 2.0)
                    {
                        __instance.produceQuality.Value = 4;
                    }
                    else if (random.NextDouble() < num2 / 2.0)
                    {
                        __instance.produceQuality.Value = 2;
                    }
                    else if (random.NextDouble() < num2)
                    {
                        __instance.produceQuality.Value = 1;
                    }
                    else
                    {
                        __instance.produceQuality.Value = 0;
                    }
                }
            }
            if (__instance.harvestType == 1 & flag2)
            {
                __instance.currentProduce.Value = parentSheetIndex;
                parentSheetIndex = -1;
            }
            if (parentSheetIndex != -1 && __instance.home != null)
            {
                bool flag3 = true;
                foreach (SObject @object in __instance.home.indoors.Value.objects.Values)
                {
                    if (@object.bigCraftable.Value && @object.parentSheetIndex.Value == 165 && @object.heldObject.Value != null)
                    {
                        if ((@object.heldObject.Value as Chest).addItem(new SObject(Vector2.Zero, parentSheetIndex, null, false, true, false, false)
                        {
                            Quality = __instance.produceQuality.Value
                        }) == null)
                        {
                            @object.showNextIndex.Value = true;
                            flag3 = false;
                            break;
                        }
                    }
                }
                if (flag3 && !__instance.home.indoors.Value.Objects.ContainsKey(__instance.getTileLocation()))
                {
                    __instance.home.indoors.Value.Objects.Add(__instance.getTileLocation(), new SObject(Vector2.Zero, parentSheetIndex, null, false, true, false, true)
                    {
                        Quality = __instance.produceQuality.Value
                    });
                }
            }
            if (!flag1)
            {
                if (__instance.fullness.Value < 30)
                {
                    __instance.moodMessage.Value = 4;
                }
                else if (__instance.happiness.Value < 30)
                {
                    __instance.moodMessage.Value = 3;
                }
                else if (__instance.happiness.Value < 200)
                {
                    __instance.moodMessage.Value = 2;
                }
                else
                {
                    __instance.moodMessage.Value = 1;
                }
            }
            if (Game1.timeOfDay < 1700)
            {
                __instance.fullness.Value = (byte)Math.Max(0, __instance.fullness.Value - __instance.fullnessDrain.Value * (1700 - Game1.timeOfDay) / 100);
            }
            __instance.fullness.Value = 0;
            if (Utility.isFestivalDay(Game1.dayOfMonth, Game1.currentSeason))
            {
                __instance.fullness.Value = 250;
            }
            __instance.reload(__instance.home);

            return(false);
        }
Exemple #4
0
 /*********
 ** Private methods
 *********/
 /// <summary>The method to call before <see cref="FarmAnimal.updateWhenNotCurrentLocation"/>.</summary>
 private static bool Before_UpdateWhenNotCurrentLocation(FarmAnimal __instance, Building currentBuilding, GameTime time, GameLocation environment)
 {
     Mod.Instance.Helper.Reflection.GetField <NetEvent1Field <int, NetInt> >(__instance, "doFarmerPushEvent").GetValue().Poll();
     Mod.Instance.Helper.Reflection.GetField <NetEvent0>(__instance, "doBuildingPokeEvent").GetValue().Poll();
     if (!Game1.shouldTimePass())
     {
         return(false);
     }
     __instance.update(time, environment, __instance.myID.Value, false);
     if (!Game1.IsMasterGame)
     {
         return(false);
     }
     if (currentBuilding != null && Game1.random.NextDouble() < 0.002 && (currentBuilding.animalDoorOpen.Value && Game1.timeOfDay < 1630) && (!Game1.isRaining && !Game1.currentSeason.Equals("winter") && environment.farmers.Count == 0))
     {
         GameLocation    locationFromName         = Mod.FindOutdoorsOf(currentBuilding);
         IAnimalLocation locationFromName_animals = (IAnimalLocation)locationFromName;
         if (locationFromName.isCollidingPosition(new Rectangle((currentBuilding.tileX.Value + currentBuilding.animalDoor.X) * 64 + 2, (currentBuilding.tileY.Value + currentBuilding.animalDoor.Y) * 64 + 2, (__instance.isCoopDweller() ? 64 : 128) - 4, 60), Game1.viewport, false, 0, false, __instance, false) || locationFromName.isCollidingPosition(new Rectangle((currentBuilding.tileX.Value + currentBuilding.animalDoor.X) * 64 + 2, (currentBuilding.tileY.Value + currentBuilding.animalDoor.Y + 1) * 64 + 2, (__instance.isCoopDweller() ? 64 : 128) - 4, 60), Game1.viewport, false, 0, false, __instance, false))
         {
             return(false);
         }
         if (locationFromName_animals.Animals.ContainsKey(__instance.myID.Value))
         {
             for (int index = locationFromName_animals.Animals.Count() - 1; index >= 0; --index)
             {
                 if (locationFromName_animals.Animals.Pairs.ElementAt(index).Key.Equals(__instance.myID.Value))
                 {
                     locationFromName_animals.Animals.Remove(__instance.myID.Value);
                     break;
                 }
             }
         }
         (currentBuilding.indoors.Value as AnimalHouse).animals.Remove(__instance.myID.Value);
         locationFromName_animals.Animals.Add(__instance.myID.Value, __instance);
         __instance.faceDirection(2);
         __instance.SetMovingDown(true);
         __instance.Position = new Vector2(currentBuilding.getRectForAnimalDoor().X, (currentBuilding.tileY.Value + currentBuilding.animalDoor.Y) * 64 - (__instance.Sprite.getHeight() * 4 - __instance.GetBoundingBox().Height) + 32);
         if (FarmAnimal.NumPathfindingThisTick < FarmAnimal.MaxPathfindingPerTick)
         {
             ++FarmAnimal.NumPathfindingThisTick;
             __instance.controller = new PathFindController(__instance, locationFromName, FarmAnimal.grassEndPointFunction, Game1.random.Next(4), false, FarmAnimal.behaviorAfterFindingGrassPatch, 200, Point.Zero);
         }
         if (__instance.controller?.pathToEndPoint == null || __instance.controller.pathToEndPoint.Count < 3)
         {
             __instance.SetMovingDown(true);
             __instance.controller = null;
         }
         else
         {
             __instance.faceDirection(2);
             __instance.Position = new Vector2(__instance.controller.pathToEndPoint.Peek().X * 64, __instance.controller.pathToEndPoint.Peek().Y * 64 - (__instance.Sprite.getHeight() * 4 - __instance.GetBoundingBox().Height) + 16);
             if (!__instance.isCoopDweller())
             {
                 __instance.position.X -= 32f;
             }
         }
         __instance.noWarpTimer = 3000;
         --currentBuilding.currentOccupants.Value;
         if (Utility.isOnScreen(__instance.getTileLocationPoint(), 192, locationFromName))
         {
             locationFromName.localSound("sandyStep");
         }
         if (environment.isTileOccupiedByFarmer(__instance.getTileLocation()) != null)
         {
             environment.isTileOccupiedByFarmer(__instance.getTileLocation()).TemporaryPassableTiles.Add(__instance.GetBoundingBox());
         }
     }
     Mod.Instance.Helper.Reflection.GetMethod(__instance, "behaviors").Invoke(time, environment);
     return(false);
 }
Exemple #5
0
 /*********
 ** Public methods
 *********/
 /// <summary>Construct an instance.</summary>
 /// <param name="gameHelper">Provides utility methods for interacting with the game code.</param>
 /// <param name="obj">The underlying in-game object.</param>
 public FarmAnimalTarget(GameHelper gameHelper, FarmAnimal obj)
     : base(gameHelper, TargetType.FarmAnimal, obj, obj.getTileLocation(), obj.Position)
 {
 }
Exemple #6
0
        /// <summary>The prefix for the DayUpdate method.</summary>
        /// <param name="environtment">The current location of the animal.</param>
        /// <param name="__instance">The <see cref="FarmAnimal"/> instance being patched.</param>
        /// <returns>False meaning the original method won't get ran.</returns>
        internal static bool DayUpdatePrefix(GameLocation environtment, FarmAnimal __instance) // TODO: check if I can correct the mispelling from the game code with Harmony still working
        {
            var random = new Random((int)(__instance.myID / 2 + Game1.stats.DaysPlayed));

            __instance.controller   = null;
            __instance.health.Value = 3;

            var hasBeenLockedOutside = false;

            // check if the animal is currently outside
            if (__instance.home != null && !(__instance.home.indoors.Value as AnimalHouse).animals.ContainsKey(__instance.myID) && environtment is Farm)
            {
                // check if they were locked outside
                if (!__instance.home.animalDoorOpen)
                {
                    __instance.moodMessage.Value = 6; // locked outside mood message
                    __instance.happiness.Value  /= (byte)2;
                    hasBeenLockedOutside         = true;
                }
                else // animal is outside but door is open, move the animal inside
                {
                    (environtment as Farm).animals.Remove(__instance.myID);
                    (__instance.home.indoors.Value as AnimalHouse).animals.Add(__instance.myID, __instance);

                    if (Game1.timeOfDay > 1800)
                    {
                        __instance.happiness.Value /= 2;
                    }

                    environtment = __instance.home.indoors;
                    __instance.setRandomPosition(environtment);

                    return(false);
                }
            }

            __instance.daysSinceLastLay.Value++;
            if (!__instance.wasPet) // check if the animal wasn't pet, if it wasn't then reduce happiness and friendship
            {
                __instance.friendshipTowardFarmer.Value = Math.Max(0, __instance.friendshipTowardFarmer - (10 - __instance.friendshipTowardFarmer / 200));
                __instance.happiness.Value = (byte)Math.Max(0, __instance.happiness - __instance.happinessDrain * 5);
            }
            __instance.wasPet.Value = false;

            // check if there is hay to eat
            if ((__instance.fullness < 200 || Game1.timeOfDay < 1700) && environtment is AnimalHouse)
            {
                for (int index = environtment.objects.Count() - 1; index >= 0; --index)
                {
                    var environmentObjects = environtment.objects.Pairs.ElementAt(index); // Key: location - Value: object
                    if (environmentObjects.Value.Name == "Hay")
                    {
                        // remove object and restore fullness
                        var objects = environtment.objects;
                        environmentObjects = environtment.objects.Pairs.ElementAt(index);
                        var location = environmentObjects.Key;
                        objects.Remove(location);
                        __instance.fullness.Value = byte.MaxValue;
                        break;
                    }
                }
            }

            // increase age of animal
            if (__instance.fullness > 200 || random.NextDouble() < (__instance.fullness - 30) / 170.0)
            {
                __instance.age.Value++;
                if (__instance.age == __instance.ageWhenMature)
                {
                    // change sprite sheet to be adult
                    __instance.Sprite.LoadTexture(Path.Combine("Animals", __instance.type.Value));

                    // make sheep harvestable
                    if (__instance.type.Value.Contains("Sheep"))
                    {
                        __instance.currentProduce.Value = __instance.defaultProduceIndex;
                    }

                    // ensure all animals are redy to produce - this is so the player doesn't need to wait a couple of days for them to produce
                    __instance.daysSinceLastLay.Value = 99;
                }

                // increase animal happiness - they increase happiness when full, even if not pet
                __instance.happiness.Value = (byte)Math.Min(byte.MaxValue, __instance.happiness + __instance.happinessDrain * 2);
            }

            // decrease animal happiness and friendship if they are hungry
            if (__instance.fullness.Value < 200)
            {
                __instance.happiness.Value = (byte)Math.Max(0, __instance.happiness - 100);
                __instance.friendshipTowardFarmer.Value = Math.Max(0, __instance.friendshipTowardFarmer - 20);
            }

            // determine whether the animal can produce an item today
            bool canProduceItem = __instance.daysSinceLastLay >= __instance.daysToLay - (!__instance.type.Value.Equals("Sheep") || !Game1.getFarmer((long)__instance.ownerID).professions.Contains(3) ? 0 : 1) && random.NextDouble() < __instance.fullness / 200.0 && random.NextDouble() < __instance.happiness / 70.0;

            var producedItemId = -1;

            if (canProduceItem && !__instance.isBaby()) // check whether the animal can produce an item and which one
            {
                var subType = ModEntry.Instance.Api.GetAnimalSubTypeByName(__instance.type.Value);
                if (subType != null)
                {
                    var numberOfHearts = (int)(__instance.friendshipTowardFarmer / 195f);
                    producedItemId = subType.Produce.GetRandomDefault(numberOfHearts, out var harvestType);
                    __instance.harvestType.Value = (byte)harvestType;
                }

                if (random.NextDouble() < __instance.happiness / 150.0)
                {
                    // create a frienship modifier based off of animal happiness - this is so deluxe item drops are also determine from animal happiness, not just friendship
                    float frienshipModifier = __instance.happiness > 200 ? __instance.happiness * 1.5f : __instance.happiness <= 100 ? __instance.happiness - 100 : 0.0f;

                    // determine deluxe products for Ducks and Rabbits separately as their deluxe products are rare drops, unlike other animals
                    if (__instance.type.Value.Equals("Duck") && random.NextDouble() < (__instance.friendshipTowardFarmer + frienshipModifier) / 5000.0 + Game1.player.team.AverageDailyLuck() + Game1.player.team.AverageLuckLevel() * 0.01)
                    {
                        producedItemId = __instance.deluxeProduceIndex;
                    }
                    else if (__instance.type.Value.Equals("Rabbit") && random.NextDouble() < (__instance.friendshipTowardFarmer + frienshipModifier) / 5000.0 + Game1.player.team.AverageDailyLuck() + Game1.player.team.AverageLuckLevel() * 0.02)
                    {
                        producedItemId = __instance.deluxeProduceIndex;
                    }

                    __instance.daysSinceLastLay.Value = 0;

                    // increase game stats for items produced - this only applies to items layable by default animals
                    switch (producedItemId)
                    {
                    case 176:
                        Game1.stats.ChickenEggsLayed++;
                        break;

                    case 180:
                        Game1.stats.ChickenEggsLayed++;
                        break;

                    case 440:
                        Game1.stats.RabbitWoolProduced++;
                        break;

                    case 442:
                        Game1.stats.DuckEggsLayed++;
                        break;
                    }

                    // determine whether deluxe product should be produced, exclude Ducks and Rabbits as they've been handled above
                    if (!__instance.type.Value.Equals("Duck") && !__instance.type.Value.Equals("Rabbit"))
                    {
                        if (random.NextDouble() < (__instance.friendshipTowardFarmer + frienshipModifier) / 1200.0 && __instance.friendshipTowardFarmer >= 200)
                        {
                            var numberOfHearts = (int)(__instance.friendshipTowardFarmer / 195f);
                            var customSubType  = ModEntry.Instance.Api.GetAnimalSubTypeByName(__instance.type.Value);
                            var deluxeId       = customSubType.Produce.GetRandomDeluxe(numberOfHearts, out var harvestType);
                            if (deluxeId != -1) // only change to a deluxe product if one could be found (not all animals have deluxe produce)
                            {
                                producedItemId = deluxeId;
                                __instance.harvestType.Value = (byte)harvestType;
                            }
                        }
                    }

                    double productQualityChance = __instance.friendshipTowardFarmer / 1000.0 - (1.0 - __instance.happiness / 225.0);

                    // if the farmer has a related profession, increase the chance of getting a high quality drop
                    if (!__instance.isCoopDweller() && Game1.getFarmer(__instance.ownerID).professions.Contains(3) || __instance.isCoopDweller() && Game1.getFarmer(__instance.ownerID).professions.Contains(2))
                    {
                        productQualityChance += 0.33;
                    }

                    // determine quality of produced item
                    if (productQualityChance >= 0.95 && random.NextDouble() < productQualityChance / 2.0)
                    {
                        __instance.produceQuality.Value = 4;
                    }
                    else if (random.NextDouble() < productQualityChance / 2.0)
                    {
                        __instance.produceQuality.Value = 2;
                    }
                    else if (random.NextDouble() < productQualityChance)
                    {
                        __instance.produceQuality.Value = 1;
                    }
                    else
                    {
                        __instance.produceQuality.Value = 0;
                    }
                }
            }

            // setup harvest type with a tool - this is so it's produce doesn't spawn in the animal house, instead must be manually harvested
            if (__instance.harvestType == 1 && canProduceItem)
            {
                __instance.currentProduce.Value = producedItemId;
                producedItemId = -1;
            }

            // ensure animal has an item ready to spawn and a valid home to spawn it in
            if (producedItemId != -1 && __instance.home != null)
            {
                var needsToPlaceProduce = true; // whether the animal needs to place there object - used for determining the the produce has been placed in an autograbber

                // check if the animal house has an auto grabber, if so spawn the item in there
                foreach (SObject environmentObject in __instance.home.indoors.Value.objects.Values)
                {
                    if (environmentObject.bigCraftable && environmentObject.parentSheetIndex == 165 && environmentObject.heldObject.Value != null)
                    {
                        var producedItem = new SObject(Vector2.Zero, producedItemId, null, false, true, false, false)
                        {
                            Quality = __instance.produceQuality
                        };
                        if ((environmentObject.heldObject.Value as Chest).addItem(producedItem) == null) // if addItem returns null it mean's all the items could be placed in the autograbber
                        {
                            environmentObject.showNextIndex.Value = true;
                            needsToPlaceProduce = false;
                            break;
                        }
                    }
                }

                // spawn the object if there was no valid auto grabber and there is a valid space under the animal
                if (needsToPlaceProduce && !__instance.home.indoors.Value.Objects.ContainsKey(__instance.getTileLocation()))
                {
                    var producedItem = new SObject(Vector2.Zero, producedItemId, null, false, true, false, true)
                    {
                        Quality = __instance.produceQuality
                    };
                    __instance.home.indoors.Value.Objects.Add(__instance.getTileLocation(), producedItem);
                }
            }

            // calculate the mood message for the animal
            if (!hasBeenLockedOutside) // ensure they haven't been locked outside, this is because a mood message would have been set already
            {
                if (__instance.fullness < 30)
                {
                    __instance.moodMessage.Value = 4;
                }
                else if (__instance.happiness < 30)
                {
                    __instance.moodMessage.Value = 3;
                }
                else if (__instance.happiness < 200)
                {
                    __instance.moodMessage.Value = 2;
                }
                else
                {
                    __instance.moodMessage.Value = 1;
                }
            }

            // make animal hungry
            __instance.fullness.Value = 0;

            // if it's a festival today, don't make animal hungry - festivals go on for most of the day so making them hungry would be unfair to the player
            if (Utility.isFestivalDay(Game1.dayOfMonth, Game1.currentSeason))
            {
                __instance.fullness.Value = 250;
            }

            // reload animal data
            __instance.reload(__instance.home);

            return(false);
        }
Exemple #7
0
        /// <summary>The prefix for the UpdateWhenNotCurrentLocation method.</summary>
        /// <param name="currentBuilding">The current building the animal is in.</param>
        /// <param name="time">The GameTime object that contains time data about the game's frame time.</param>
        /// <param name="environment">The <see cref="GameLocation"/> of the animal.</param>
        /// <returns>False meaning the original method won't get ran.</returns>
        internal static bool UpdateWhenNotCurrentLocationPrefix(Building currentBuilding, GameTime time, GameLocation environment, FarmAnimal __instance)
        {
            var behaviors           = typeof(FarmAnimal).GetMethod("behaviors", BindingFlags.NonPublic | BindingFlags.Instance);
            var doFarmerPushEvent   = (NetEvent1Field <int, NetInt>) typeof(FarmAnimal).GetField("doFarmerPushEvent", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(__instance);
            var doBuildingPokeEvent = (NetEvent0)typeof(FarmAnimal).GetField("doBuildingPokeEvent", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(__instance);

            doFarmerPushEvent.Poll();
            doBuildingPokeEvent.Poll();

            // skip if time is paused
            if (!Game1.shouldTimePass())
            {
                return(false);
            }

            __instance.update(time, environment, __instance.myID, false);

            // ensure this is the game host (not the farmhands)
            if (!Game1.IsMasterGame)
            {
                return(false);
            }

            // check if the animal is able to go outside
            if (currentBuilding == null || Game1.random.NextDouble() > .002 || !currentBuilding.animalDoorOpen || Game1.timeOfDay >= 1630 || Game1.isRaining || environment.farmers.Count > 0)
            {
                behaviors.Invoke(__instance, new object[] { time, environment });
                return(false);
            }

            // check for special season conditions on the animal
            var animal = ModEntry.Instance.Api.GetAnimalBySubTypeName(__instance.type);

            if (animal != null)
            {
                // convert season string value into enum
                Season season = Season.Spring;
                switch (Game1.currentSeason)
                {
                case "summer":
                    season = Season.Summer;
                    break;

                case "fall":
                    season = Season.Fall;
                    break;

                case "winter":
                    season = Season.Winter;
                    break;
                }

                if (!animal.Data.SeasonsAllowedOutdoors.Contains(season))
                {
                    behaviors.Invoke(__instance, new object[] { time, environment });
                    return(false);
                }
            }

            // get the farm location to spawn the animal in
            Farm farm = (Farm)Game1.getLocationFromName("Farm");

            // ensure the animal won't be colliding with anything when they leave the house
            var exitCollisionBox = new Rectangle(
                x: (currentBuilding.tileX + currentBuilding.animalDoor.X) * 64 + 2,
                y: (currentBuilding.tileY + currentBuilding.animalDoor.Y) * 64 + 2,
                width: __instance.isCoopDweller() ? 60 : 124,
                height: 60
                );

            if (farm.isCollidingPosition(exitCollisionBox, Game1.viewport, false, 0, false, __instance, false, false, false))
            {
                return(false);
            }

            // remove animal from farm
            if (farm.animals.ContainsKey(__instance.myID))
            {
                for (int index = farm.animals.Count() - 1; index >= 0; --index)
                {
                    if (farm.animals.Pairs.ElementAt(index).Key.Equals(__instance.myID))
                    {
                        farm.animals.Remove(__instance.myID);
                        break;
                    }
                }
            }

            // remove animal from building
            (currentBuilding.indoors.Value as AnimalHouse).animals.Remove(__instance.myID);

            // add animal to farm, initial values
            farm.animals.Add(__instance.myID, __instance);
            __instance.faceDirection(2);
            __instance.SetMovingDown(true);
            __instance.Position = new Vector2((float)currentBuilding.getRectForAnimalDoor().X, (float)((currentBuilding.tileY + currentBuilding.animalDoor.Y) * 64 - (__instance.Sprite.getHeight() * 4 - __instance.GetBoundingBox().Height) + 32));

            // sort out path finding
            if (FarmAnimal.NumPathfindingThisTick < FarmAnimal.MaxPathfindingPerTick)
            {
                ++FarmAnimal.NumPathfindingThisTick;
                __instance.controller = new PathFindController(
                    c: __instance,
                    location: farm,
                    endFunction: new PathFindController.isAtEnd(FarmAnimal.grassEndPointFunction),
                    finalFacingDirection: Game1.random.Next(4),
                    eraseOldPathController: false,
                    endBehaviorFunction: new PathFindController.endBehavior(FarmAnimal.behaviorAfterFindingGrassPatch),
                    limit: 200,
                    endPoint: Point.Zero
                    );
            }

            if (__instance.controller == null || __instance.controller.pathToEndPoint == null || __instance.controller.pathToEndPoint.Count < 3)
            {
                __instance.SetMovingDown(true);
                __instance.controller = null;
            }
            else
            {
                __instance.faceDirection(2);
                __instance.Position = new Vector2(
                    x: __instance.controller.pathToEndPoint.Peek().X * 64,
                    y: (__instance.controller.pathToEndPoint.Peek().Y * 64 - (__instance.Sprite.getHeight() * 4 - __instance.GetBoundingBox().Height) + 16)
                    );

                if (!__instance.isCoopDweller())
                {
                    __instance.position.X -= 32f;
                }
            }

            __instance.noWarpTimer = 3000;
            currentBuilding.currentOccupants.Value--;
            if (Utility.isOnScreen(__instance.getTileLocationPoint(), 192, farm))
            {
                farm.localSound("sandyStep");
            }

            if (environment.isTileOccupiedByFarmer(__instance.getTileLocation()) != null)
            {
                environment.isTileOccupiedByFarmer(__instance.getTileLocation()).TemporaryPassableTiles.Add(__instance.GetBoundingBox());
            }

            behaviors.Invoke(__instance, new object[] { time, environment });
            return(false);
        }
Exemple #8
0
        /// <summary>The prefix for the FindTruffle method.</summary>
        /// <remarks>Although the method is called 'FindTruffle' it's responsible for all produce that is foraged.</remarks>
        /// <param name="__instance">The current <see cref="FarmAnimal"/> instance being patched.</param>
        /// <returns>False meaning the original method won't get ran.</returns>
        public static bool FindTrufflePrefix(FarmAnimal __instance)
        {
            // detemine the item to drop
            var productId = -1;
            var subType   = ModEntry.Instance.Api.GetAnimalSubTypeByName(__instance.type);

            if (subType != null)
            {
                // get all the foragable items
                var foragableItems = subType.Produce?.AllSeasons?.Products?.Where(product => product.HarvestType == HarvestType.Forage).Select(product => product.Id).ToList();
                switch (Game1.currentSeason)
                {
                case "spring":
                {
                    var products = subType.Produce?.Spring?.Products?.Where(produce => produce.HarvestType == HarvestType.Forage).Select(produce => produce.Id).ToList();
                    if (products != null)
                    {
                        foragableItems.AddRange(products);
                    }

                    break;
                }

                case "summer":
                {
                    var products = subType.Produce?.Summer?.Products?.Where(produce => produce.HarvestType == HarvestType.Forage).Select(produce => produce.Id).ToList();
                    if (products != null)
                    {
                        foragableItems.AddRange(products);
                    }

                    break;
                }

                case "fall":
                {
                    var products = subType.Produce?.Fall?.Products?.Where(produce => produce.HarvestType == HarvestType.Forage).Select(produce => produce.Id).ToList();
                    if (products != null)
                    {
                        foragableItems.AddRange(products);
                    }

                    break;
                }

                case "winter":
                {
                    var products = subType.Produce?.Winter?.Products?.Where(produce => produce.HarvestType == HarvestType.Forage).Select(produce => produce.Id).ToList();
                    if (products != null)
                    {
                        foragableItems.AddRange(products);
                    }

                    break;
                }
                }

                if (foragableItems.Count == 0)
                {
                    return(false);
                }

                var productStringId = foragableItems[Game1.random.Next(foragableItems.Count)];
                if (!int.TryParse(productStringId, out productId))
                {
                    return(false);
                }
            }

            // try to spawn the product around the animal
            if (Utility.spawnObjectAround(Utility.getTranslatedVector2(__instance.getTileLocation(), __instance.FacingDirection, 1f), new SObject(__instance.getTileLocation(), productId, 1), Game1.getFarm(), true))
            {
                if (productId == 430)
                {
                    ++Game1.stats.TrufflesFound;
                }
            }

            // if the player is a high friendship, increase the possiblility of skipping resetting the currentProduce - this means high friendshipped animals produce more
            if (Game1.random.NextDouble() <= __instance.friendshipTowardFarmer / 1500.0)
            {
                return(false);
            }

            __instance.currentProduce.Value = -1;
            return(false);
        }