/// <summary>The method to call before <see cref="FarmAnimal.behaviors"/>.</summary> public static bool Before_Behaviors(FarmAnimal __instance, GameTime time, GameLocation location, ref bool __result) { if (__instance.home == null) { __result = false; return(false); } if (__instance.isEating.Value) { if (__instance.home != null && __instance.home.getRectForAnimalDoor().Intersects(__instance.GetBoundingBox())) { FarmAnimal.behaviorAfterFindingGrassPatch(__instance, location); __instance.isEating.Value = false; __instance.Halt(); __result = false; return(false); } if (__instance.buildingTypeILiveIn.Contains("Barn")) { __instance.Sprite.Animate(time, 16, 4, 100f); if (__instance.Sprite.currentFrame >= 20) { __instance.isEating.Value = false; __instance.Sprite.loop = true; __instance.Sprite.currentFrame = 0; __instance.faceDirection(2); } } else { __instance.Sprite.Animate(time, 24, 4, 100f); if (__instance.Sprite.currentFrame >= 28) { __instance.isEating.Value = false; __instance.Sprite.loop = true; __instance.Sprite.currentFrame = 0; __instance.faceDirection(2); } } __result = true; return(false); } if (!Game1.IsClient) { if (__instance.controller != null) { __result = true; return(false); } if (location.IsOutdoors && __instance.fullness.Value < 195 && (Game1.random.NextDouble() < 0.002 && FarmAnimal.NumPathfindingThisTick < FarmAnimal.MaxPathfindingPerTick)) { ++FarmAnimal.NumPathfindingThisTick; __instance.controller = new PathFindController(__instance, location, FarmAnimal.grassEndPointFunction, -1, false, FarmAnimal.behaviorAfterFindingGrassPatch, 200, Point.Zero); } if (Game1.timeOfDay >= 1700 && location.IsOutdoors && (__instance.controller == null && Game1.random.NextDouble() < 0.002)) { if (location.farmers.Count == 0) { (location as Farm).animals.Remove(__instance.myID.Value); (__instance.home.indoors.Value as AnimalHouse).animals.Add(__instance.myID.Value, __instance); __instance.setRandomPosition(__instance.home.indoors.Value); __instance.faceDirection(Game1.random.Next(4)); __instance.controller = null; __result = true; return(false); } if (FarmAnimal.NumPathfindingThisTick < FarmAnimal.MaxPathfindingPerTick) { ++FarmAnimal.NumPathfindingThisTick; __instance.controller = new PathFindController(__instance, location, PathFindController.isAtEndPoint, 0, false, null, 200, new Point(__instance.home.tileX.Value + __instance.home.animalDoor.X, __instance.home.tileY.Value + __instance.home.animalDoor.Y)); } } if (location.IsOutdoors && !Game1.isRaining && (!Game1.currentSeason.Equals("winter") && __instance.currentProduce.Value != -1) && (__instance.age.Value >= __instance.ageWhenMature.Value && __instance.type.Value.Contains("Pig") && Game1.random.NextDouble() < 0.0002)) { Rectangle boundingBox = __instance.GetBoundingBox(); for (int corner = 0; corner < 4; ++corner) { Vector2 cornersOfThisRectangle = Utility.getCornersOfThisRectangle(ref boundingBox, corner); Vector2 key = new Vector2((int)(cornersOfThisRectangle.X / 64.0), (int)(cornersOfThisRectangle.Y / 64.0)); if (location.terrainFeatures.ContainsKey(key) || location.objects.ContainsKey(key)) { __result = false; return(false); } } if (Game1.player.currentLocation.Equals(location)) { DelayedAction.playSoundAfterDelay("dirtyHit", 450); DelayedAction.playSoundAfterDelay("dirtyHit", 900); DelayedAction.playSoundAfterDelay("dirtyHit", 1350); } if (location.Equals(Game1.currentLocation)) { var findTruffleDelegate = (AnimatedSprite.endOfAnimationBehavior)Delegate.CreateDelegate(typeof(AnimatedSprite.endOfAnimationBehavior), Mod.Instance.Helper.Reflection.GetMethod(__instance, "findTruffle").MethodInfo); switch (__instance.FacingDirection) { case 0: __instance.Sprite.setCurrentAnimation(new List <FarmerSprite.AnimationFrame> { new(9, 250), new(11, 250), new(9, 250), new(11, 250), new(9, 250), new(11, 250, false, false, findTruffleDelegate) }); break;
/********* ** 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); }
/// <summary>The method to call before <see cref="FarmAnimal.updateWhenCurrentLocation"/>.</summary> private static bool Before_UpdateWhenCurrentLocation(FarmAnimal __instance, GameTime time, GameLocation location, ref bool __result) { if (!Game1.shouldTimePass()) { return(false); } if (__instance.health.Value <= 0) { return(true); } Mod.Instance.Helper.Reflection.GetField <NetEvent0>(__instance, "doBuildingPokeEvent").GetValue().Poll(); if (__instance.hitGlowTimer > 0) { __instance.hitGlowTimer -= time.ElapsedGameTime.Milliseconds; } if (__instance.Sprite.CurrentAnimation != null) { if (__instance.Sprite.animateOnce(time)) { __instance.Sprite.CurrentAnimation = null; } return(false); } __instance.update(time, location, __instance.myID.Value, false); if (Game1.IsMasterGame && Mod.Instance.Helper.Reflection.GetMethod(__instance, "behaviors").Invoke <bool>(time, location) || __instance.Sprite.CurrentAnimation != null) { return(false); } if (__instance.controller != null && __instance.controller.timerSinceLastCheckPoint > 10000) { __instance.controller = null; __instance.Halt(); } if (location is BuildableGameLocation && location is IAnimalLocation animalLocation && __instance.noWarpTimer <= 0) { Building building = __instance.home; if (building != null && Game1.IsMasterGame && building.getRectForAnimalDoor().Contains(__instance.GetBoundingBox().Center.X, __instance.GetBoundingBox().Top)) { if (Utility.isOnScreen(__instance.getTileLocationPoint(), 192, location)) { location.localSound("dwoop"); } animalLocation.Animals.Remove(__instance.myID.Value); (building.indoors.Value as AnimalHouse).animals[__instance.myID.Value] = __instance; __instance.setRandomPosition(building.indoors.Value); __instance.faceDirection(Game1.random.Next(4)); __instance.controller = null; return(true); } } __instance.noWarpTimer = Math.Max(0, __instance.noWarpTimer - time.ElapsedGameTime.Milliseconds); if (__instance.pauseTimer > 0) { __instance.pauseTimer -= time.ElapsedGameTime.Milliseconds; } if (Game1.timeOfDay >= 2000) { __instance.Sprite.currentFrame = __instance.buildingTypeILiveIn.Contains("Coop") ? 16 : 12; __instance.Sprite.UpdateSourceRect(); __instance.FacingDirection = 2; if (!__instance.isEmoting && Game1.random.NextDouble() < 0.002) { __instance.doEmote(24); } } else if (__instance.pauseTimer <= 0) { if (Game1.random.NextDouble() < 0.001 && __instance.age.Value >= __instance.ageWhenMature.Value && (Game1.gameMode == 3 && __instance.sound.Value != null) && Utility.isOnScreen(__instance.Position, 192)) { __instance.makeSound(); } if (!Game1.IsClient && Game1.random.NextDouble() < 0.007 && __instance.uniqueFrameAccumulator == -1) { int direction = Game1.random.Next(5); if (direction != (__instance.FacingDirection + 2) % 4) { if (direction < 4) { int facingDirection = __instance.FacingDirection; __instance.faceDirection(direction); if (!location.IsOutdoors && location.isCollidingPosition(__instance.nextPosition(direction), Game1.viewport, __instance)) { __instance.faceDirection(facingDirection); return(false); } } switch (direction) { case 0: __instance.SetMovingUp(true); break; case 1: __instance.SetMovingRight(true); break; case 2: __instance.SetMovingDown(true); break; case 3: __instance.SetMovingLeft(true); break; default: __instance.Halt(); __instance.Sprite.StopAnimation(); break; } } else if (__instance.noWarpTimer <= 0) { __instance.Halt(); __instance.Sprite.StopAnimation(); } } if (!Game1.IsClient && __instance.isMoving() && (Game1.random.NextDouble() < 0.014 && __instance.uniqueFrameAccumulator == -1)) { __instance.Halt(); __instance.Sprite.StopAnimation(); if (Game1.random.NextDouble() < 0.75) { __instance.uniqueFrameAccumulator = 0; if (__instance.buildingTypeILiveIn.Contains("Coop")) { switch (__instance.FacingDirection) { case 0: __instance.Sprite.currentFrame = 20; break; case 1: __instance.Sprite.currentFrame = 18; break; case 2: __instance.Sprite.currentFrame = 16; break; case 3: __instance.Sprite.currentFrame = 22; break; } } else if (__instance.buildingTypeILiveIn.Contains("Barn")) { switch (__instance.FacingDirection) { case 0: __instance.Sprite.currentFrame = 15; break; case 1: __instance.Sprite.currentFrame = 14; break; case 2: __instance.Sprite.currentFrame = 13; break; case 3: __instance.Sprite.currentFrame = 14; break; } } } __instance.Sprite.UpdateSourceRect(); } if (__instance.uniqueFrameAccumulator != -1 && !Game1.IsClient) { __instance.uniqueFrameAccumulator += time.ElapsedGameTime.Milliseconds; if (__instance.uniqueFrameAccumulator > 500) { if (__instance.buildingTypeILiveIn.Contains("Coop")) { __instance.Sprite.currentFrame = __instance.Sprite.currentFrame + 1 - __instance.Sprite.currentFrame % 2 * 2; } else if (__instance.Sprite.currentFrame > 12) { __instance.Sprite.currentFrame = (__instance.Sprite.currentFrame - 13) * 4; } else { switch (__instance.FacingDirection) { case 0: __instance.Sprite.currentFrame = 15; break; case 1: __instance.Sprite.currentFrame = 14; break; case 2: __instance.Sprite.currentFrame = 13; break; case 3: __instance.Sprite.currentFrame = 14; break; } } __instance.uniqueFrameAccumulator = 0; if (Game1.random.NextDouble() < 0.4) { __instance.uniqueFrameAccumulator = -1; } } } else if (!Game1.IsClient) { __instance.MovePosition(time, Game1.viewport, location); } } return(false); }
public static bool beginUsing(MilkPail __instance, GameLocation location, int x, int y, StardewValley.Farmer who, ref bool __result) { if (!IsFeedingBasket(__instance)) { return(true); } string feedingBasketId = __instance.modData[FeedingBasketKey]; x = (int)who.GetToolLocation(false).X; y = (int)who.GetToolLocation(false).Y; Rectangle rectangle = new Rectangle(x - Game1.tileSize / 2, y - Game1.tileSize / 2, Game1.tileSize, Game1.tileSize); // Added this because for some wierd reason the current value appears subtracted by 5 the first time the tool is used. __instance.CurrentParentTileIndex = InitialParentTileIndex; if (!DataLoader.ModConfig.DisableTreats) { if (location is Farm farm) { foreach (FarmAnimal farmAnimal in farm.animals.Values) { if (farmAnimal.GetBoundingBox().Intersects(rectangle)) { Animals[feedingBasketId] = farmAnimal; break; } } if (!Animals.ContainsKey(feedingBasketId) || Animals[feedingBasketId] == null) { foreach (Pet localPet in farm.characters.Where(i => i is Pet)) { if (localPet.GetBoundingBox().Intersects(rectangle)) { Pets[feedingBasketId] = localPet; break; } } } } else if (location is AnimalHouse animalHouse) { foreach (FarmAnimal farmAnimal in animalHouse.animals.Values) { if (farmAnimal.GetBoundingBox().Intersects(rectangle)) { Animals[feedingBasketId] = farmAnimal; break; } } } else if (location is FarmHouse) { foreach (Pet localPet in location.characters.Where(i => i is Pet)) { if (localPet.GetBoundingBox().Intersects(rectangle)) { Pets[feedingBasketId] = localPet; break; } } } } Animals.TryGetValue(feedingBasketId, out FarmAnimal animal); if (animal != null) { string dialogue = ""; if (__instance.attachments[0] == null) { if (who != null && Game1.player.Equals(who)) { Game1.showRedMessage(DataLoader.i18n.Get("Tool.FeedingBasket.Empty")); } Animals[feedingBasketId] = animal = null; } else if (!TreatsController.CanReceiveTreat(animal)) { dialogue = DataLoader.i18n.Get("Tool.FeedingBasket.NotLikeTreat", new { itemName = __instance.attachments[0].DisplayName }); } else if (!TreatsController.IsLikedTreat(animal, __instance.attachments[0])) { dialogue = DataLoader.i18n.Get("Tool.FeedingBasket.NotLikeTreat", new { itemName = __instance.attachments[0].DisplayName }); } else if (__instance.attachments[0].Category == SObject.MilkCategory && !animal.isBaby()) { dialogue = DataLoader.i18n.Get("Tool.FeedingBasket.OnlyBabiesCanEatMilk"); } else if (!TreatsController.IsReadyForTreat(animal)) { if (TreatsController.GetTreatItem(animal)?.MinimumDaysBetweenTreats == 1) { dialogue = DataLoader.i18n.Get("Tool.FeedingBasket.AlreadyAteTreatToday", new { animalName = animal.displayName }); } else { int daysUntilNextTreat = TreatsController.DaysUntilNextTreat(animal); if (daysUntilNextTreat > 1) { dialogue = DataLoader.i18n.Get("Tool.FeedingBasket.WantsTreatInDays", new { animalName = animal.displayName, numberOfDays = daysUntilNextTreat }); } else if (daysUntilNextTreat == 1) { dialogue = DataLoader.i18n.Get("Tool.FeedingBasket.WantsTreatTomorrow", new { animalName = animal.displayName }); } } } else { animal.pauseTimer = 1000; } if (dialogue.Length > 0) { if (who != null && Game1.player.Equals(who)) { DelayedAction.showDialogueAfterDelay(dialogue, 150); } Animals[feedingBasketId] = animal = null; } } Pets.TryGetValue(feedingBasketId, out Pet pet); if (pet != null) { string dialogue = ""; if (__instance.attachments[0] == null) { if (who != null && Game1.player.Equals(who)) { Game1.showRedMessage(DataLoader.i18n.Get("Tool.FeedingBasket.Empty")); } Pets[feedingBasketId] = pet = null; } else if (!TreatsController.IsLikedTreat(pet, __instance.attachments[0])) { dialogue = DataLoader.i18n.Get("Tool.FeedingBasket.NotLikeTreat", new { itemName = __instance.attachments[0].DisplayName }); } else if (!TreatsController.IsReadyForTreat(pet)) { int daysUntilNextTreat = TreatsController.DaysUntilNextTreat(pet); if (DataLoader.AnimalData.Pet.MinimumDaysBetweenTreats == 1) { dialogue = DataLoader.i18n.Get("Tool.FeedingBasket.AlreadyAteTreatToday", new { animalName = pet.displayName }); } else if (daysUntilNextTreat > 1) { dialogue = DataLoader.i18n.Get("Tool.FeedingBasket.WantsTreatInDays", new { animalName = pet.displayName, numberOfDays = daysUntilNextTreat }); } else if (daysUntilNextTreat == 1) { dialogue = DataLoader.i18n.Get("Tool.FeedingBasket.WantsTreatTomorrow", new { animalName = pet.displayName }); } } else { pet.Halt(); pet.FacingDirection = 2; pet.CurrentBehavior = 2; DataLoader.Helper.Reflection.GetField <int>(pet, "_currentBehavior").SetValue(2); pet.Halt(); pet.Sprite.setCurrentAnimation(new List <FarmerSprite.AnimationFrame>() { new FarmerSprite.AnimationFrame(18, 200) }); pet.Sprite.loop = true; } if (dialogue.Length > 0) { if (who != null && Game1.player.Equals(who)) { DelayedAction.showDialogueAfterDelay(dialogue, 150); } Pets[feedingBasketId] = pet = null; } } who.Halt(); int currentFrame = who.FarmerSprite.currentFrame; if (animal != null || pet != null) { switch (who.FacingDirection) { case 0: who.FarmerSprite.animateOnce(new FarmerSprite.AnimationFrame[1] { new FarmerSprite.AnimationFrame(62, 900, false, false, new AnimatedSprite.endOfAnimationBehavior(StardewValley.Farmer.useTool), true) }); break; case 1: who.FarmerSprite.animateOnce(new FarmerSprite.AnimationFrame[1] { new FarmerSprite.AnimationFrame(58, 900, false, false, new AnimatedSprite.endOfAnimationBehavior(StardewValley.Farmer.useTool), true) }); break; case 2: who.FarmerSprite.animateOnce(new FarmerSprite.AnimationFrame[1] { new FarmerSprite.AnimationFrame(54, 900, false, false, new AnimatedSprite.endOfAnimationBehavior(StardewValley.Farmer.useTool), true) }); break; case 3: who.FarmerSprite.animateOnce(new FarmerSprite.AnimationFrame[1] { new FarmerSprite.AnimationFrame(58, 900, false, true, new AnimatedSprite.endOfAnimationBehavior(StardewValley.Farmer.useTool), true) }); break; } } else { who.FarmerSprite.animateOnce(new FarmerSprite.AnimationFrame[1] { new FarmerSprite.AnimationFrame(currentFrame, 0, false, who.FacingDirection == 3, new AnimatedSprite.endOfAnimationBehavior(StardewValley.Farmer.useTool), true) }); } who.FarmerSprite.oldFrame = currentFrame; who.UsingTool = true; who.CanMove = false; if (animal != null || pet != null) { Rectangle boundingBox; boundingBox = animal != null?animal.GetBoundingBox() : pet.GetBoundingBox(); double numX = boundingBox.Center.X; double numY = boundingBox.Center.Y; Vector2 vectorBasket = new Vector2((float)numX - 32, (float)numY); Vector2 vectorFood = new Vector2((float)numX - 24, (float)numY - 10); var foodScale = Game1.pixelZoom * 0.75f; TemporaryAnimatedSprite basketSprite = new TemporaryAnimatedSprite(Game1.toolSpriteSheetName, Game1.getSourceRectForStandardTileSheet(Game1.toolSpriteSheet, __instance.CurrentParentTileIndex, 16, 16), 750.0f, 1, 1, vectorBasket, false, false, ((float)boundingBox.Bottom + 0.1f) / 10000f, 0.0f, Color.White, Game1.pixelZoom, 0.0f, 0.0f, 0.0f) { delayBeforeAnimationStart = 100 }; location.temporarySprites.Add(basketSprite); TemporaryAnimatedSprite foodSprite = new TemporaryAnimatedSprite(Game1.objectSpriteSheetName, Game1.getSourceRectForStandardTileSheet(Game1.objectSpriteSheet, __instance.attachments[0].ParentSheetIndex, 16, 16), 500.0f, 1, 1, vectorFood, false, false, ((float)boundingBox.Bottom + 0.2f) / 10000f, 0.0f, Color.White, foodScale, 0.0f, 0.0f, 0.0f) { delayBeforeAnimationStart = 100 }; location.temporarySprites.Add(foodSprite); for (int index = 0; index < 8; ++index) { Rectangle standardTileSheet = Game1.getSourceRectForStandardTileSheet(Game1.objectSpriteSheet, __instance.attachments[0].ParentSheetIndex, 16, 16); standardTileSheet.X += 8; standardTileSheet.Y += 8; standardTileSheet.Width = Game1.pixelZoom; standardTileSheet.Height = Game1.pixelZoom; TemporaryAnimatedSprite temporaryAnimatedSprite2 = new TemporaryAnimatedSprite(Game1.objectSpriteSheetName, standardTileSheet, 400f, 1, 0, vectorFood + new Vector2(12, 12), false, false, ((float)boundingBox.Bottom + 0.2f) / 10000f, 0.0f, Color.White, (float)foodScale, 0.0f, 0.0f, 0.0f, false) { motion = new Vector2((float)Game1.random.Next(-30, 31) / 10f, (float)Game1.random.Next(-6, -3)), acceleration = new Vector2(0.0f, 0.5f), delayBeforeAnimationStart = 600 }; location.temporarySprites.Add(temporaryAnimatedSprite2); } if (animal != null) { FarmAnimal tempAnimal = animal; Game1.delayedActions.Add(new DelayedAction(300, new DelayedAction.delayedBehavior(() => { if (tempAnimal.buildingTypeILiveIn.Contains("Barn")) { tempAnimal.Sprite.setCurrentAnimation(new List <FarmerSprite.AnimationFrame> { new FarmerSprite.AnimationFrame(16, 100), new FarmerSprite.AnimationFrame(17, 100), new FarmerSprite.AnimationFrame(18, 100), new FarmerSprite.AnimationFrame(19, 100), new FarmerSprite.AnimationFrame(19, 100, secondaryArm: false, flip: false, (f) => { tempAnimal.doEmote(20, true); tempAnimal.Sprite.CurrentAnimation = null; tempAnimal.Sprite.loop = true; tempAnimal.Sprite.currentFrame = 0; tempAnimal.faceDirection(2); }) }); } else { tempAnimal.Sprite.setCurrentAnimation(new List <FarmerSprite.AnimationFrame> { new FarmerSprite.AnimationFrame(24, 100), new FarmerSprite.AnimationFrame(25, 100), new FarmerSprite.AnimationFrame(26, 100), new FarmerSprite.AnimationFrame(27, 100), new FarmerSprite.AnimationFrame(27, 100, secondaryArm: false, flip: false, (f) => { tempAnimal.doEmote(20, true); tempAnimal.Sprite.CurrentAnimation = null; tempAnimal.Sprite.loop = true; tempAnimal.Sprite.currentFrame = 0; tempAnimal.faceDirection(2); }) }); } tempAnimal.Sprite.loop = false; }))); } else if (pet != null) { pet.Sprite.setCurrentAnimation(new List <FarmerSprite.AnimationFrame>() { new FarmerSprite.AnimationFrame(18, 300), new FarmerSprite.AnimationFrame(17, 100), new FarmerSprite.AnimationFrame(16, 100), new FarmerSprite.AnimationFrame(0, 100), new FarmerSprite.AnimationFrame(16, 100), new FarmerSprite.AnimationFrame(17, 100, secondaryArm: false, flip: false, (f) => pet.doEmote(20, true), true), new FarmerSprite.AnimationFrame(18, 300, false, false, pet.hold, true) }); pet.Sprite.loop = false; } if (who != null && Game1.player.Equals(who)) { DelayedAction.playSoundAfterDelay("eat", 600, location); } } __result = true; return(false); }
/// <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); }
/// <summary>The prefix for the Behaviors method.</summary> /// <param name="time">The GameTime object that contains time data about the game's frame time.</param> /// <param name="location">The current location of the <see cref="FarmAnimal"/> being patched.</param> /// <param name="__result">The return value of the original Bahaviors method.</param> /// <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 BehaviorsPrefix(GameTime time, GameLocation location, ref bool __result, FarmAnimal __instance) { // ensure animal has a house if (__instance.home == null) { __result = false; return(false); } // get isEating memeber var isEating = (NetBool)typeof(FarmAnimal).GetField("isEating", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(__instance); if (isEating) { if (__instance.home != null && __instance.home.getRectForAnimalDoor().Intersects(__instance.GetBoundingBox())) { FarmAnimal.behaviorAfterFindingGrassPatch(__instance, location); isEating.Value = false; __instance.Halt(); __result = false; return(false); } // sort out animation if (__instance.buildingTypeILiveIn.Contains("Barn")) { __instance.Sprite.Animate(time, 16, 4, 100f); if (__instance.Sprite.currentFrame >= 20) { isEating.Value = false; __instance.Sprite.loop = true; __instance.Sprite.currentFrame = 0; __instance.faceDirection(2); } } else { __instance.Sprite.Animate(time, 24, 4, 100f); if (__instance.Sprite.currentFrame >= 28) { isEating.Value = false; __instance.Sprite.loop = true; __instance.Sprite.currentFrame = 0; __instance.faceDirection(2); } } // set isEating member typeof(FarmAnimal).GetField("isEating", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(__instance, isEating); __result = true; return(false); } // only let the main behavior code be ran by the host if (Game1.IsClient) { __result = false; return(false); } // ensure animal isn't currently on a path if (__instance.controller != null) { __result = true; return(false); } // make animal go to grass if it's hungry if (location.IsOutdoors && __instance.fullness < 195 && (Game1.random.NextDouble() < 0.002 && FarmAnimal.NumPathfindingThisTick < FarmAnimal.MaxPathfindingPerTick)) { FarmAnimal.NumPathfindingThisTick++; __instance.controller = new PathFindController(__instance, location, new PathFindController.isAtEnd(FarmAnimal.grassEndPointFunction), -1, false, new PathFindController.endBehavior(FarmAnimal.behaviorAfterFindingGrassPatch), 200, Point.Zero, true); } // teleport the animals inside at night if (Game1.timeOfDay >= 1700 && location.IsOutdoors && (__instance.controller == null && Game1.random.NextDouble() < 0.002)) { if (location.farmers.Count == 0) { (location as Farm).animals.Remove(__instance.myID); (__instance.home.indoors.Value as AnimalHouse).animals.Add(__instance.myID, __instance); __instance.setRandomPosition(__instance.home.indoors); __instance.faceDirection(Game1.random.Next(4)); __instance.controller = null; __result = true; return(false); } if (FarmAnimal.NumPathfindingThisTick < FarmAnimal.MaxPathfindingPerTick) { ++FarmAnimal.NumPathfindingThisTick; __instance.controller = new PathFindController(__instance, location, new PathFindController.isAtEnd(PathFindController.isAtEndPoint), 0, false, null, 200, new Point(__instance.home.tileX + __instance.home.animalDoor.X, __instance.home.tileY + __instance.home.animalDoor.Y), true); } } // check if animal can forage for produce if (location.IsOutdoors && !Game1.isRaining && __instance.currentProduce != -1 && !__instance.isBaby() && Game1.random.NextDouble() < 0.0002) { // check if animal has produce that can be foraged var subType = ModEntry.Instance.Api.GetAnimalSubTypeByName(__instance.type); if (subType != null) { // get the forage items count var productCount = subType.Produce?.AllSeasons?.Products.Where(product => product.HarvestType == HarvestType.Forage).Select(product => product.Id).Count() ?? 0; switch (Game1.currentSeason) { case "spring": { productCount += subType.Produce?.Spring?.Products.Where(produce => produce.HarvestType == HarvestType.Forage).Select(produce => produce.Id).Count() ?? 0; productCount += subType.Produce?.Spring?.DeluxeProducts.Where(produce => produce.HarvestType == HarvestType.Forage).Select(produce => produce.Id).Count() ?? 0; break; } case "summer": { productCount = subType.Produce?.Spring?.Products.Where(produce => produce.HarvestType == HarvestType.Forage).Select(produce => produce.Id).Count() ?? 0; productCount = subType.Produce?.Spring?.DeluxeProducts.Where(produce => produce.HarvestType == HarvestType.Forage).Select(produce => produce.Id).Count() ?? 0; break; } case "fall": { productCount = subType.Produce?.Spring?.Products.Where(produce => produce.HarvestType == HarvestType.Forage).Select(produce => produce.Id).Count() ?? 0; productCount = subType.Produce?.Spring?.DeluxeProducts.Where(produce => produce.HarvestType == HarvestType.Forage).Select(produce => produce.Id).Count() ?? 0; break; } case "winter": { productCount = subType.Produce?.Spring?.Products.Where(produce => produce.HarvestType == HarvestType.Forage).Select(produce => produce.Id).Count() ?? 0; productCount = subType.Produce?.Spring?.DeluxeProducts.Where(produce => produce.HarvestType == HarvestType.Forage).Select(produce => produce.Id).Count() ?? 0; break; } } // ensure there is a valid product for the animal if (productCount == 0) { __result = false; return(false); } } // amke sure the place is blank for spawning the foraged item var boundingBox = __instance.GetBoundingBox(); for (int corner = 0; corner < 4; ++corner) { var cornersOfThisRectangle = Utility.getCornersOfThisRectangle(ref boundingBox, corner); var position = new Vector2(cornersOfThisRectangle.X / 64f, cornersOfThisRectangle.Y / 64f); if (location.terrainFeatures.ContainsKey(position) || location.objects.ContainsKey(position)) { __result = false; return(false); } } // play forage sounds if (Game1.player.currentLocation.Equals(location)) { DelayedAction.playSoundAfterDelay("dirtyHit", 450, null, -1); DelayedAction.playSoundAfterDelay("dirtyHit", 900, null, -1); DelayedAction.playSoundAfterDelay("dirtyHit", 1350, null, -1); } // animate the animal is the player is there var findTruffle = typeof(FarmAnimal).GetMethod("findTruffle", BindingFlags.NonPublic | BindingFlags.Instance); if (location.Equals(Game1.currentLocation)) { switch (__instance.FacingDirection) { case 0: __instance.Sprite.setCurrentAnimation(new List <FarmerSprite.AnimationFrame>() { new FarmerSprite.AnimationFrame(9, 250), new FarmerSprite.AnimationFrame(11, 250), new FarmerSprite.AnimationFrame(9, 250), new FarmerSprite.AnimationFrame(11, 250), new FarmerSprite.AnimationFrame(9, 250), new FarmerSprite.AnimationFrame(11, 250, false, false, new AnimatedSprite.endOfAnimationBehavior((farmer) => { findTruffle.Invoke(__instance, new object[] { farmer }); }), false) }); break; case 1: __instance.Sprite.setCurrentAnimation(new List <FarmerSprite.AnimationFrame>() { new FarmerSprite.AnimationFrame(5, 250), new FarmerSprite.AnimationFrame(7, 250), new FarmerSprite.AnimationFrame(5, 250), new FarmerSprite.AnimationFrame(7, 250), new FarmerSprite.AnimationFrame(5, 250), new FarmerSprite.AnimationFrame(7, 250, false, false, new AnimatedSprite.endOfAnimationBehavior((farmer) => { findTruffle.Invoke(__instance, new object[] { farmer }); }), false) }); break; case 2: __instance.Sprite.setCurrentAnimation(new List <FarmerSprite.AnimationFrame>() { new FarmerSprite.AnimationFrame(1, 250), new FarmerSprite.AnimationFrame(3, 250), new FarmerSprite.AnimationFrame(1, 250), new FarmerSprite.AnimationFrame(3, 250), new FarmerSprite.AnimationFrame(1, 250), new FarmerSprite.AnimationFrame(3, 250, false, false, new AnimatedSprite.endOfAnimationBehavior((farmer) => { findTruffle.Invoke(__instance, new object[] { farmer }); }), false) }); break; case 3: __instance.Sprite.setCurrentAnimation(new List <FarmerSprite.AnimationFrame>() { new FarmerSprite.AnimationFrame(5, 250, false, true, (AnimatedSprite.endOfAnimationBehavior)null, false), new FarmerSprite.AnimationFrame(7, 250, false, true, (AnimatedSprite.endOfAnimationBehavior)null, false), new FarmerSprite.AnimationFrame(5, 250, false, true, (AnimatedSprite.endOfAnimationBehavior)null, false), new FarmerSprite.AnimationFrame(7, 250, false, true, (AnimatedSprite.endOfAnimationBehavior)null, false), new FarmerSprite.AnimationFrame(5, 250, false, true, (AnimatedSprite.endOfAnimationBehavior)null, false), new FarmerSprite.AnimationFrame(7, 250, false, true, new AnimatedSprite.endOfAnimationBehavior((farmer) => { findTruffle.Invoke(__instance, new object[] { farmer }); }), false) }); break; } __instance.Sprite.loop = false; } else { findTruffle.Invoke(__instance, new object[] { Game1.player }); } } __result = false; return(false); }
public static bool Prefix(FarmAnimal __instance, GameTime time, GameLocation location, ref bool __result) { NetBool isEating = Mod.instance.Helper.Reflection.GetField <NetBool>(__instance, "isEating").GetValue(); if (__instance.home == null) { __result = false; return(false); } if (( bool )(NetFieldBase <bool, NetBool>)isEating) { if (__instance.home != null && __instance.home.getRectForAnimalDoor().Intersects(__instance.GetBoundingBox())) { FarmAnimal.behaviorAfterFindingGrassPatch(( Character )__instance, location); isEating.Value = false; __instance.Halt(); __result = false; return(false); } if (__instance.buildingTypeILiveIn.Contains("Barn")) { __instance.Sprite.Animate(time, 16, 4, 100f); if (__instance.Sprite.currentFrame >= 20) { isEating.Value = false; __instance.Sprite.loop = true; __instance.Sprite.currentFrame = 0; __instance.faceDirection(2); } } else { __instance.Sprite.Animate(time, 24, 4, 100f); if (__instance.Sprite.currentFrame >= 28) { isEating.Value = false; __instance.Sprite.loop = true; __instance.Sprite.currentFrame = 0; __instance.faceDirection(2); } } __result = true; return(false); } if (!Game1.IsClient) { if (__instance.controller != null) { __result = true; return(false); } if (location.IsOutdoors && ( byte )(NetFieldBase <byte, NetByte>)__instance.fullness < ( byte )195 && (Game1.random.NextDouble() < 0.002 && FarmAnimal.NumPathfindingThisTick < FarmAnimal.MaxPathfindingPerTick)) { ++FarmAnimal.NumPathfindingThisTick; __instance.controller = new PathFindController(( Character )__instance, location, new PathFindController.isAtEnd(FarmAnimal.grassEndPointFunction), -1, false, new PathFindController.endBehavior(FarmAnimal.behaviorAfterFindingGrassPatch), 200, Point.Zero, true); } if (Game1.timeOfDay >= 1700 && location.IsOutdoors && (__instance.controller == null && Game1.random.NextDouble() < 0.002)) { if (location.farmers.Count == 0) { (location as Farm).animals.Remove(( long )__instance.myID); (__instance.home.indoors.Value as AnimalHouse).animals.Add(( long )__instance.myID, __instance); __instance.setRandomPosition(( GameLocation )(NetFieldBase <GameLocation, NetRef <GameLocation> >)__instance.home.indoors); __instance.faceDirection(Game1.random.Next(4)); __instance.controller = ( PathFindController )null; __result = true; return(false); } if (FarmAnimal.NumPathfindingThisTick < FarmAnimal.MaxPathfindingPerTick) { ++FarmAnimal.NumPathfindingThisTick; __instance.controller = new PathFindController(( Character )__instance, location, new PathFindController.isAtEnd(PathFindController.isAtEndPoint), 0, false, (PathFindController.endBehavior)null, 200, new Point(( int )(NetFieldBase <int, NetInt>)__instance.home.tileX + __instance.home.animalDoor.X, ( int )(NetFieldBase <int, NetInt>)__instance.home.tileY + __instance.home.animalDoor.Y), true); } } if (location.IsOutdoors && !Game1.isRaining && (!Game1.currentSeason.Equals("winter") && ( int )(NetFieldBase <int, NetInt>)__instance.currentProduce != -1) && (( int )(NetFieldBase <int, NetInt>)__instance.age >= ( int )( byte )(NetFieldBase <byte, NetByte>)__instance.ageWhenMature && __instance.type.Value.Contains("Pig") && Game1.random.NextDouble() < 0.0002)) { Microsoft.Xna.Framework.Rectangle boundingBox = __instance.GetBoundingBox(); for (int corner = 0; corner < 4; ++corner) { Vector2 cornersOfThisRectangle = Utility.getCornersOfThisRectangle(ref boundingBox, corner); Vector2 key = new Vector2((float)(int)((double)cornersOfThisRectangle.X / 64.0), (float)(int)((double)cornersOfThisRectangle.Y / 64.0)); if (location.terrainFeatures.ContainsKey(key) || location.objects.ContainsKey(key)) { __result = false; return(false); } } if (Game1.player.currentLocation.Equals(location)) { DelayedAction.playSoundAfterDelay("dirtyHit", 450, ( GameLocation )null, -1); DelayedAction.playSoundAfterDelay("dirtyHit", 900, ( GameLocation )null, -1); DelayedAction.playSoundAfterDelay("dirtyHit", 1350, ( GameLocation )null, -1); } if (location.Equals(Game1.currentLocation)) { var findTruffleDelegate = (AnimatedSprite.endOfAnimationBehavior)Delegate.CreateDelegate(typeof(AnimatedSprite.endOfAnimationBehavior), Mod.instance.Helper.Reflection.GetMethod(__instance, "findTruffle").MethodInfo); switch (__instance.FacingDirection) { case 0: __instance.Sprite.setCurrentAnimation(new List <FarmerSprite.AnimationFrame>() { new FarmerSprite.AnimationFrame(9, 250), new FarmerSprite.AnimationFrame(11, 250), new FarmerSprite.AnimationFrame(9, 250), new FarmerSprite.AnimationFrame(11, 250), new FarmerSprite.AnimationFrame(9, 250), new FarmerSprite.AnimationFrame(11, 250, false, false, findTruffleDelegate, false) }); break; case 1: __instance.Sprite.setCurrentAnimation(new List <FarmerSprite.AnimationFrame>() { new FarmerSprite.AnimationFrame(5, 250), new FarmerSprite.AnimationFrame(7, 250), new FarmerSprite.AnimationFrame(5, 250), new FarmerSprite.AnimationFrame(7, 250), new FarmerSprite.AnimationFrame(5, 250), new FarmerSprite.AnimationFrame(7, 250, false, false, findTruffleDelegate, false) }); break; case 2: __instance.Sprite.setCurrentAnimation(new List <FarmerSprite.AnimationFrame>() { new FarmerSprite.AnimationFrame(1, 250), new FarmerSprite.AnimationFrame(3, 250), new FarmerSprite.AnimationFrame(1, 250), new FarmerSprite.AnimationFrame(3, 250), new FarmerSprite.AnimationFrame(1, 250), new FarmerSprite.AnimationFrame(3, 250, false, false, findTruffleDelegate, false) }); break; case 3: __instance.Sprite.setCurrentAnimation(new List <FarmerSprite.AnimationFrame>() { new FarmerSprite.AnimationFrame(5, 250, false, true, (AnimatedSprite.endOfAnimationBehavior)null, false), new FarmerSprite.AnimationFrame(7, 250, false, true, (AnimatedSprite.endOfAnimationBehavior)null, false), new FarmerSprite.AnimationFrame(5, 250, false, true, (AnimatedSprite.endOfAnimationBehavior)null, false), new FarmerSprite.AnimationFrame(7, 250, false, true, (AnimatedSprite.endOfAnimationBehavior)null, false), new FarmerSprite.AnimationFrame(5, 250, false, true, (AnimatedSprite.endOfAnimationBehavior)null, false), new FarmerSprite.AnimationFrame(7, 250, false, true, findTruffleDelegate, false) }); break; } __instance.Sprite.loop = false; } else { Mod.instance.Helper.Reflection.GetMethod(__instance, "findTruffle").Invoke(Game1.player); } } } __result = false; return(false); }