private static void Postfix(AnimalQueryMenu __instance, ref TextBox ___textBox)
        {
            //replace TextBox
            TextBox_ textBox_ = new TextBox_(null, null, Game1.dialogueFont, Game1.textColor);

            textBox_.X      = ___textBox.X;
            textBox_.Y      = ___textBox.Y;
            textBox_.Width  = ___textBox.Width;
            textBox_.Height = ___textBox.Height;
            textBox_.SetText(___textBox.Text);
            ___textBox = textBox_;
        }
        /// <summary>
        /// Gets the animal associated with the menu
        /// </summary>
        /// <param name="menu"></param>
        /// <returns>The animal</returns>
        public static FarmAnimal GetAnimal(this AnimalQueryMenu menu)
        {
            var reflector = StaticReflectionHelper.GetInstance().GetReflector();

            return(reflector.GetField <FarmAnimal>(menu, "animal").GetValue());
        }
        /// <summary>
        /// Returns if the animal is currently being placed or not
        /// </summary>
        /// <param name="menu"></param>
        /// <returns></returns>
        public static bool IsAnimalPlacementMode(this AnimalQueryMenu menu)
        {
            var reflector = StaticReflectionHelper.GetInstance().GetReflector();

            return(reflector.GetField <bool>(menu, "movingAnimal").GetValue());
        }
 /*********
 ** Internal Methods
 *********/
 /// <summary>The prefix for the <see cref="AnimalQueryMenu(FarmAnimal)"/> constructor.</summary>
 /// <param name="animal">The animal the menu is for.</param>
 /// <param name="__instance">The <see cref="AnimalQueryMenu"/> instance being patched.</param>
 /// <returns><see langword="false"/>, meaning the original method will not get ran.</returns>
 /// <remarks>This is used stop the original constructor from running, this is because it had a tendency to throw errors with custom animals.</remarks>
 internal static bool ConstructorPrefix(FarmAnimal animal, AnimalQueryMenu __instance)
 {
     // set the animal property, this is required as this is what gets retrieved when swapping to the custom menu
     typeof(AnimalQueryMenu).GetField("animal", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(__instance, animal);
     return(false);
 }
        /// <summary>The prefix for the Draw method.</summary>
        /// <param name="b">The <see cref="SpriteBatch"/> to draw the menu to..</param>
        /// <param name="__instance">The <see cref="AnimatedSprite"/> instance being patched.</param>
        /// <returns>False meaning the original method won't get ran.</returns>
        internal static bool DrawPrefix(SpriteBatch b, AnimalQueryMenu __instance)
        {
            // get private members
            var movingAnimal   = (bool)typeof(AnimalQueryMenu).GetField("movingAnimal", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(__instance);
            var animal         = (FarmAnimal)typeof(AnimalQueryMenu).GetField("animal", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(__instance);
            var textBox        = (TextBox)typeof(AnimalQueryMenu).GetField("textBox", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(__instance);
            var parentName     = (string)typeof(AnimalQueryMenu).GetField("parentName", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(__instance);
            var loveLevel      = (double)typeof(AnimalQueryMenu).GetField("loveLevel", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(__instance);
            var confirmingSell = (bool)typeof(AnimalQueryMenu).GetField("confirmingSell", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(__instance);
            var hoverText      = (string)typeof(AnimalQueryMenu).GetField("hoverText", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(__instance);

            // player is viewing main animal query menu
            if (!movingAnimal && !Game1.globalFade)
            {
                // dark background
                b.Draw(
                    texture: Game1.fadeToBlackRect,
                    destinationRectangle: Game1.graphics.GraphicsDevice.Viewport.Bounds,
                    color: Color.Black * 0.75f
                    );

                // menu background
                Game1.drawDialogueBox(
                    x: __instance.xPositionOnScreen,
                    y: __instance.yPositionOnScreen + 128,
                    width: AnimalQueryMenu.width,
                    height: AnimalQueryMenu.height - 128,
                    speaker: false,
                    drawOnlyBox: true
                    );

                if (animal.harvestType != (byte)2)
                {
                    textBox.Draw(b);
                }

                // construct age string
                int    monthsOld = (animal.age + 1) / 28 + 1;
                string ageString = monthsOld <= 1
                    ? Game1.content.LoadString(Path.Combine("Strings", "UI:AnimalQuery_Age1"))
                    : Game1.content.LoadString(Path.Combine("Strings", "UI:AnimalQuery_AgeN"), monthsOld);

                // if the animal is a baby, add ' (Baby)' onto the age string
                if (animal.age < animal.ageWhenMature)
                {
                    ageString += Game1.content.LoadString(Path.Combine("Strings", "UI:AnimalQuery_AgeBaby"));
                }

                // draw age string
                Utility.drawTextWithShadow(
                    b: b,
                    text: ageString,
                    font: Game1.smallFont,
                    position: new Vector2(
                        x: __instance.xPositionOnScreen + IClickableMenu.spaceToClearSideBorder + 32,
                        y: __instance.yPositionOnScreen + IClickableMenu.spaceToClearTopBorder + 16 + 128),
                    color: Game1.textColor
                    );

                // draw the parent of the animal
                int parentWidthOffset = 0;
                if (parentName != null)
                {
                    parentWidthOffset = 21;
                    Utility.drawTextWithShadow(
                        b: b,
                        text: Game1.content.LoadString(Path.Combine("Strings", "UI:AnimalQuery_Parent"), parentName),
                        font: Game1.smallFont,
                        position: new Vector2(
                            x: __instance.xPositionOnScreen + IClickableMenu.spaceToClearSideBorder + 32,
                            y: __instance.yPositionOnScreen + IClickableMenu.spaceToClearTopBorder + 32 + 16 + 128),
                        color: Game1.textColor
                        );
                }

                // get whether a partial heart should be drawn (and in what heart it should be drawn)
                int partialHeartLocation = loveLevel * 1000f % 200f >= 100.0
                    ? (int)(loveLevel * 1000f / 200f)
                    : -100;

                // draw the 5 animal friendship hearts
                for (int i = 0; i < 5; i++)
                {
                    // draw heart background
                    b.Draw(
                        texture: Game1.mouseCursors,
                        position: new Vector2(
                            x: (float)(__instance.xPositionOnScreen + 96 + 32 * i),
                            y: (float)(parentWidthOffset + __instance.yPositionOnScreen - 32 + 320)),
                        sourceRectangle: new Rectangle(
                            x: 211 + (loveLevel * 1000.0 <= (double)((i + 1) * 195) ? 7 : 0),
                            y: 428,
                            width: 7,
                            height: 6),
                        color: Color.White,
                        rotation: 0,
                        origin: Vector2.Zero,
                        scale: 4,
                        effects: SpriteEffects.None,
                        layerDepth: 0.89f
                        );

                    if (partialHeartLocation == i)
                    {
                        // draw partially filled heart
                        b.Draw(
                            texture: Game1.mouseCursors,
                            position: new Vector2(
                                x: (float)(__instance.xPositionOnScreen + 96 + 32 * i),
                                y: (float)(parentWidthOffset + __instance.yPositionOnScreen - 32 + 320)),
                            sourceRectangle: new Rectangle(
                                x: 211,
                                y: 428,
                                width: 4,
                                height: 6),
                            color: Color.White,
                            rotation: 0,
                            origin: Vector2.Zero,
                            scale: 4,
                            effects: SpriteEffects.None,
                            layerDepth: 0.891f
                            );
                    }
                }

                // draw mood message
                Utility.drawTextWithShadow(
                    b: b,
                    text: Game1.parseText(animal.getMoodMessage(), Game1.smallFont, AnimalQueryMenu.width - IClickableMenu.spaceToClearSideBorder * 2 - 64),
                    font: Game1.smallFont,
                    position: new Vector2(
                        x: __instance.xPositionOnScreen + IClickableMenu.spaceToClearSideBorder + 32,
                        y: parentWidthOffset + __instance.yPositionOnScreen + 384 - 64 + 4),
                    color: Game1.textColor
                    );

                __instance.okButton.draw(b);
                __instance.sellButton.draw(b);
                __instance.moveHomeButton.draw(b);

                if (__instance.allowReproductionButton != null)
                {
                    __instance.allowReproductionButton.draw(b);
                }

                if (confirmingSell)
                {
                    // draw dark background
                    b.Draw(
                        texture: Game1.fadeToBlackRect,
                        destinationRectangle: Game1.graphics.GraphicsDevice.Viewport.Bounds,
                        color: Color.Black * 0.75f
                        );

                    // draw sell confirmation background
                    Game1.drawDialogueBox(
                        x: Game1.viewport.Width / 2 - 160,
                        y: Game1.viewport.Height / 2 - 192,
                        width: 320,
                        height: 256,
                        speaker: false,
                        drawOnlyBox: true
                        );

                    // draw 'Are you sure?' message
                    var message = "Are you sure?";
                    b.DrawString(
                        spriteFont: Game1.dialogueFont,
                        text: message,
                        position: new Vector2(
                            x: Game1.viewport.Width / 2f - Game1.dialogueFont.MeasureString(message).X / 2f,
                            y: Game1.viewport.Height / 2f - 96 + 8),
                        color: Game1.textColor
                        );

                    // draw yes/no buttons
                    __instance.yesButton.draw(b);
                    __instance.noButton.draw(b);
                }
                else if (hoverText != null && hoverText.Length > 0)
                {
                    // draw hover text
                    IClickableMenu.drawHoverText(
                        b: b,
                        text: hoverText,
                        font: Game1.smallFont
                        );
                }
            }
            else if (!Game1.globalFade) // player is choosing a new home for the animal
            {
                // construct housing string
                var customAnimal    = ModEntry.Instance.Api.GetAnimalBySubTypeName(animal.type);
                var buildingsString = "";

                for (var i = 0; i < customAnimal.Data.Buildings.Count; i++)
                {
                    var building = customAnimal.Data.Buildings[i];
                    buildingsString += building;
                    if (i != customAnimal.Data.Buildings.Count - 1)
                    {
                        buildingsString += ", ";
                    }
                }

                var housingString = $"Please choose a: {buildingsString} for your {animal.type}";

                // housing string background
                Game1.drawDialogueBox(
                    x: 32,
                    y: -64,
                    width: (int)Game1.dialogueFont.MeasureString(housingString).X + IClickableMenu.borderWidth * 2 + 16,
                    height: 128 + IClickableMenu.borderWidth * 2,
                    speaker: false,
                    drawOnlyBox: true
                    );

                // draw housing string
                b.DrawString(
                    spriteFont: Game1.dialogueFont,
                    text: housingString,
                    position: new Vector2(
                        x: 32 + IClickableMenu.spaceToClearSideBorder * 2 + 8,
                        y: 44f),
                    color: Game1.textColor
                    );

                // draw ok button
                __instance.okButton.draw(b);
            }

            // draw cursor
            __instance.drawMouse(b);

            return(false);
        }
        /// <summary>The prefix for the PerformHoverAction method.</summary>
        /// <param name="x">The X position of the cursor.</param>
        /// <param name="y">The Y position of the cursor.</param>
        /// <param name="__instance">The current instance being patched.</param>
        /// <returns>False meaning the original method won't get ran.</returns>
        internal static bool PerformHoverActionPrefix(int x, int y, AnimalQueryMenu __instance)
        {
            // get private members
            var movingAnimal = (bool)typeof(AnimalQueryMenu).GetField("movingAnimal", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(__instance);
            var animal       = (FarmAnimal)typeof(AnimalQueryMenu).GetField("animal", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(__instance);

            var hoverText = "";

            if (movingAnimal) // the player is choosing a new home for the animal
            {
                var tile = new Vector2((x + Game1.viewport.X) / 64, (y + Game1.viewport.Y) / 64);
                var farm = Game1.getLocationFromName("Farm") as Farm;

                // highlight all buildings white
                foreach (Building building in farm.buildings)
                {
                    building.color.Value = Color.White;
                }

                // check the building the player is currently hovering on
                Building hoveredBuilding = farm.getBuildingAt(tile);
                if (hoveredBuilding != null)
                {
                    // set the highlight color of the currently hovered building based on if the animal can live in the building
                    var highLightColor = Color.Red * .8f;;

                    // get animal data
                    var customAnimal = ModEntry.Instance.Api.GetAnimalBySubTypeName(animal.type);
                    if (customAnimal != null)
                    {
                        foreach (var building in customAnimal.Data.Buildings)
                        {
                            if (hoveredBuilding.buildingType.Value.ToLower() == building.ToLower() && !(hoveredBuilding.indoors.Value as AnimalHouse).isFull())
                            {
                                highLightColor = Color.LightGreen * .8f;
                            }
                        }
                    }

                    hoveredBuilding.color.Value = highLightColor;
                }
            }

            // change scale ('zoom in') of buttons when player hover on them
            // ok button
            if (__instance.okButton != null)
            {
                if (__instance.okButton.containsPoint(x, y))
                {
                    __instance.okButton.scale = Math.Min(1.1f, __instance.okButton.scale + 0.05f);
                }
                else
                {
                    __instance.okButton.scale = Math.Max(1f, __instance.okButton.scale - 0.05f);
                }
            }

            // sell button
            if (__instance.sellButton != null)
            {
                if (__instance.sellButton.containsPoint(x, y))
                {
                    __instance.sellButton.scale = Math.Min(4.1f, __instance.sellButton.scale + 0.05f);
                    hoverText = Game1.content.LoadString(Path.Combine("Strings", "UI:AnimalQuery_Sell"), animal.getSellPrice());
                }
                else
                {
                    __instance.sellButton.scale = Math.Max(4f, __instance.sellButton.scale - 0.05f);
                }
            }

            // move home button
            if (__instance.moveHomeButton != null)
            {
                if (__instance.moveHomeButton.containsPoint(x, y))
                {
                    __instance.moveHomeButton.scale = Math.Min(4.1f, __instance.moveHomeButton.scale + 0.05f);
                    hoverText = Game1.content.LoadString(Path.Combine("Strings", "UI:AnimalQuery_Move"));
                }
                else
                {
                    __instance.moveHomeButton.scale = Math.Max(4f, __instance.moveHomeButton.scale - 0.05f);
                }
            }

            // allow reproduction button
            if (__instance.allowReproductionButton != null)
            {
                if (__instance.allowReproductionButton.containsPoint(x, y))
                {
                    __instance.allowReproductionButton.scale = Math.Min(4.1f, __instance.allowReproductionButton.scale + 0.05f);
                    hoverText = Game1.content.LoadString(Path.Combine("Strings", "UI:AnimalQuery_AllowReproduction"));
                }
                else
                {
                    __instance.allowReproductionButton.scale = Math.Max(4f, __instance.allowReproductionButton.scale - 0.05f);
                }
            }

            // yes button
            if (__instance.yesButton != null)
            {
                if (__instance.yesButton.containsPoint(x, y))
                {
                    __instance.yesButton.scale = Math.Min(1.1f, __instance.yesButton.scale + 0.05f);
                }
                else
                {
                    __instance.yesButton.scale = Math.Max(1f, __instance.yesButton.scale - 0.05f);
                }
            }

            // no button
            if (__instance.noButton != null)
            {
                if (__instance.noButton.containsPoint(x, y))
                {
                    __instance.noButton.scale = Math.Min(1.1f, __instance.noButton.scale + 0.05f);
                }
                else
                {
                    __instance.noButton.scale = Math.Max(1f, __instance.noButton.scale - 0.05f);
                }
            }

            // set private members
            typeof(AnimalQueryMenu).GetField("hoverText", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(__instance, hoverText);
            return(false);
        }
        /// <summary>The prefix for the ReceiveLeftClick method.</summary>
        /// <param name="x">The X position of the cursor.</param>
        /// <param name="y">The Y position of the cursor.</param>
        /// <param name="__instance">The current instance being patched.</param>
        /// <returns>False meaning the original method won't get ran.</returns>
        internal static bool ReceiveLeftClickPrefix(int x, int y, AnimalQueryMenu __instance)
        {
            if (Game1.globalFade)
            {
                return(false);
            }

            // get private members
            var movingAnimal   = (bool)typeof(AnimalQueryMenu).GetField("movingAnimal", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(__instance);
            var animal         = (FarmAnimal)typeof(AnimalQueryMenu).GetField("animal", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(__instance);
            var confirmingSell = (bool)typeof(AnimalQueryMenu).GetField("confirmingSell", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(__instance);
            var textBox        = (TextBox)typeof(AnimalQueryMenu).GetField("textBox", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(__instance);
            var multiplayer    = (Multiplayer)typeof(Game1).GetField("multiplayer", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null);

            if (movingAnimal) // if the player is currently choosing a new home for the animal
            {
                if (__instance.okButton != null && __instance.okButton.containsPoint(x, y))
                {
                    Game1.globalFadeToBlack(new Game1.afterFadeFunction(__instance.prepareForReturnFromPlacement), 0.02f);
                    Game1.playSound("smallSelect");
                }

                // the building currently under the cursor
                var      tile       = new Vector2((x + Game1.viewport.X) / 64, (y + Game1.viewport.Y) / 64);
                var      farm       = Game1.getLocationFromName("Farm") as Farm;
                Building buildingAt = farm.getBuildingAt(tile);
                if (buildingAt == null)
                {
                    return(false);
                }

                var isBuildingValid = true;
                var customAnimal    = ModEntry.Instance.Api.GetAnimalBySubTypeName(animal.type);
                if (customAnimal != null)
                {
                    // keep track of whether the animal can live in the building to determine whether to display the 'I Can't Live Here' message
                    var canAnimalLiveHere = false;
                    foreach (var building in customAnimal.Data.Buildings)
                    {
                        if (buildingAt.buildingType.Value.ToLower() == building.ToLower())
                        {
                            canAnimalLiveHere = true;
                            if ((buildingAt.indoors.Value as AnimalHouse).isFull())
                            {
                                Game1.showRedMessage(Game1.content.LoadString(Path.Combine("Strings", "UI:AnimalQuery_Moving_BuildingFull")));
                                isBuildingValid = false;
                            }
                            else if (buildingAt.Equals(animal.home))
                            {
                                Game1.showRedMessage(Game1.content.LoadString(Path.Combine("Strings", "UI:AnimalQuery_Moving_AlreadyHome")));
                                isBuildingValid = false;
                            }
                        }
                    }

                    if (!canAnimalLiveHere)
                    {
                        Game1.showRedMessage(Game1.content.LoadString(Path.Combine("Strings", "UI:AnimalQuery_Moving_CantLiveThere"), animal.shortDisplayType()));
                        isBuildingValid = false;
                    }
                }

                // if the building is valid, move the animal to it
                if (isBuildingValid)
                {
                    (animal.home.indoors.Value as AnimalHouse).animalsThatLiveHere.Remove(animal.myID);

                    if ((animal.home.indoors.Value as AnimalHouse).animals.ContainsKey(animal.myID))
                    {
                        (buildingAt.indoors.Value as AnimalHouse).animals.Add(animal.myID, animal);
                        (animal.home.indoors.Value as AnimalHouse).animals.Remove(animal.myID);
                    }

                    animal.home = buildingAt;
                    animal.homeLocation.Value = new Vector2(buildingAt.tileX, buildingAt.tileY);
                    (buildingAt.indoors.Value as AnimalHouse).animalsThatLiveHere.Add(animal.myID);
                    animal.makeSound();
                    Game1.globalFadeToBlack(new Game1.afterFadeFunction(__instance.finishedPlacingAnimal), 0.02f);
                }
            }
            else if (confirmingSell) // the player is selling the animal
            {
                if (__instance.yesButton.containsPoint(x, y))
                {
                    Game1.player.Money += animal.getSellPrice();
                    (animal.home.indoors.Value as AnimalHouse).animalsThatLiveHere.Remove(animal.myID);
                    animal.health.Value = -1;

                    // draw the green puffs of smoke
                    int numberOfSmokeAnimations = animal.frontBackSourceRect.Width / 2;
                    for (int i = 0; i < numberOfSmokeAnimations; i++)
                    {
                        int colourVariationAmount = Game1.random.Next(25, 200);
                        multiplayer.broadcastSprites(
                            location: Game1.currentLocation,
                            sprites: new TemporaryAnimatedSprite(
                                rowInAnimationTexture: 5,
                                position: animal.Position + new Vector2(
                                    x: Game1.random.Next(-32, animal.frontBackSourceRect.Width * 3),
                                    y: Game1.random.Next(-32, animal.frontBackSourceRect.Height * 3)),
                                color: new Color(
                                    r: byte.MaxValue - colourVariationAmount,
                                    g: byte.MaxValue,
                                    b: byte.MaxValue - colourVariationAmount),
                                animationInterval: Game1.random.NextDouble() < 0.5 ? 50f : Game1.random.Next(30, 200),
                                sourceRectWidth: 64,
                                sourceRectHeight: 64,
                                delay: Game1.random.NextDouble() < 0.5 ? 0 : Game1.random.Next(0, 600)
                                )
                        {
                            scale  = Game1.random.Next(2, 5) * 0.25f,
                            alpha  = Game1.random.Next(2, 5) * 0.25f,
                            motion = new Vector2(0.0f, (float)-Game1.random.NextDouble())
                        });
                    }

                    Game1.playSound("newRecipe");
                    Game1.playSound("money");
                    Game1.exitActiveMenu();
                }
                else if (__instance.noButton.containsPoint(x, y))
                {
                    confirmingSell = false;
                    Game1.playSound("smallSelect");

                    if (Game1.options.SnappyMenus)
                    {
                        __instance.currentlySnappedComponent = __instance.getComponentWithID(103);
                        __instance.snapCursorToCurrentSnappedComponent();
                    }
                }
            }
            else // player is in the main query menu
            {
                // close menu
                if (__instance.okButton != null && __instance.okButton.containsPoint(x, y) && __instance.readyToClose())
                {
                    Game1.exitActiveMenu();

                    if (textBox.Text.Length > 0 && !Utility.areThereAnyOtherAnimalsWithThisName(textBox.Text))
                    {
                        animal.displayName = textBox.Text;
                        animal.Name        = textBox.Text;
                    }

                    Game1.playSound("smallSelect");
                }

                // sell animal - brings up animal confirmation dialogue
                if (__instance.sellButton.containsPoint(x, y))
                {
                    confirmingSell = true;

                    // create yes button
                    var yesButton = new ClickableTextureComponent(
                        bounds: new Rectangle(
                            x: Game1.viewport.Width / 2 - 64 - 4,
                            y: Game1.viewport.Height / 2 - 32,
                            width: 64,
                            height: 64),
                        texture: Game1.mouseCursors,
                        sourceRect: Game1.getSourceRectForStandardTileSheet(
                            tileSheet: Game1.mouseCursors,
                            tilePosition: 46),
                        scale: 1
                        );
                    yesButton.myID            = 111;
                    yesButton.rightNeighborID = 105;
                    __instance.yesButton      = yesButton;

                    // create no button
                    var noButton = new ClickableTextureComponent(
                        bounds: new Rectangle(
                            x: Game1.viewport.Width / 2 + 4,
                            y: Game1.viewport.Height / 2 - 32,
                            width: 64,
                            height: 64),
                        texture: Game1.mouseCursors,
                        sourceRect: Game1.getSourceRectForStandardTileSheet(
                            tileSheet: Game1.mouseCursors,
                            tilePosition: 47),
                        scale: 1
                        );
                    noButton.myID           = 105;
                    noButton.leftNeighborID = 111;
                    __instance.noButton     = noButton;

                    Game1.playSound("smallSelect");

                    if (Game1.options.SnappyMenus)
                    {
                        __instance.populateClickableComponentList();
                        __instance.currentlySnappedComponent = __instance.noButton;
                        __instance.snapCursorToCurrentSnappedComponent();
                    }
                }
                else if (__instance.moveHomeButton.containsPoint(x, y)) // player is abount to rehouse animal
                {
                    Game1.playSound("smallSelect");
                    Game1.globalFadeToBlack(new Game1.afterFadeFunction(__instance.prepareForAnimalPlacement), 0.02f);
                }
                else if (__instance.allowReproductionButton != null && __instance.allowReproductionButton.containsPoint(x, y)) // player is toggling whether the animal can reproduce
                {
                    Game1.playSound("drumkit6");
                    animal.allowReproduction.Value = !animal.allowReproduction;
                    __instance.allowReproductionButton.sourceRect.X = !animal.allowReproduction ? 137 : 128;
                }
                else
                {
                    textBox.Update();
                }
            }

            // set private members
            typeof(AnimalQueryMenu).GetField("animal", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(__instance, animal);
            typeof(AnimalQueryMenu).GetField("confirmingSell", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(__instance, confirmingSell);

            return(false);
        }
        internal static void AnimalQueryMenuPatch(AnimalQueryMenu __instance, bool ___confirmingSell, FarmAnimal ___animal, TextBox ___textBox, string ___parentName)
        {
            try
            {
                int    x = Game1.getMouseX(true), y = Game1.getMouseY(true);                                               // Mouse x and y position
                bool   isCPressed = MainClass.Config.PrimaryInfoKey.JustPressed();                                         // For narrating animal details
                bool   isEscPressed = Game1.input.GetKeyboardState().IsKeyDown(Microsoft.Xna.Framework.Input.Keys.Escape); // For escaping/unselecting from the animal name text box
                string toSpeak = " ", details = " ";

                if (___textBox.Selected)
                {
                    toSpeak = ___textBox.Text;

                    if (isEscPressed)
                    {
                        ___textBox.Selected = false;
                    }
                }
                else
                {
                    if (isCPressed & !isNarratingAnimalInfo)
                    {
                        string name    = ___animal.displayName;
                        string type    = ___animal.displayType;
                        int    age     = (___animal.GetDaysOwned() + 1) / 28 + 1;
                        string ageText = (age <= 1) ? Game1.content.LoadString("Strings\\UI:AnimalQuery_Age1") : Game1.content.LoadString("Strings\\UI:AnimalQuery_AgeN", age);
                        string parent  = "";
                        if ((int)___animal.age.Value < (byte)___animal.ageWhenMature.Value)
                        {
                            ageText += Game1.content.LoadString("Strings\\UI:AnimalQuery_AgeBaby");
                        }
                        if (___parentName != null)
                        {
                            parent = Game1.content.LoadString("Strings\\UI:AnimalQuery_Parent", ___parentName);
                        }

                        details = $"Name: {name} Type: {type} \n\t Age: {ageText} {parent}";
                        animalQueryMenuQuery = " ";

                        isNarratingAnimalInfo = true;
                        Task.Delay(200).ContinueWith(_ => { isNarratingAnimalInfo = false; });
                    }

                    if (__instance.okButton != null && __instance.okButton.containsPoint(x, y))
                    {
                        toSpeak = "OK button";
                    }
                    else if (__instance.sellButton != null && __instance.sellButton.containsPoint(x, y))
                    {
                        toSpeak = $"Sell for {___animal.getSellPrice()}g button";
                    }
                    else if (___confirmingSell && __instance.yesButton != null && __instance.yesButton.containsPoint(x, y))
                    {
                        toSpeak = "Confirm selling animal";
                    }
                    else if (___confirmingSell && __instance.noButton != null && __instance.noButton.containsPoint(x, y))
                    {
                        toSpeak = "Cancel selling animal";
                    }
                    else if (__instance.moveHomeButton != null && __instance.moveHomeButton.containsPoint(x, y))
                    {
                        toSpeak = "Change home building button";
                    }
                    else if (__instance.allowReproductionButton != null && __instance.allowReproductionButton.containsPoint(x, y))
                    {
                        toSpeak = ((___animal.allowReproduction.Value) ? "Enabled" : "Disabled") + " allow reproduction button";
                    }
                    else if (__instance.textBoxCC != null && __instance.textBoxCC.containsPoint(x, y))
                    {
                        toSpeak = "Animal name text box";
                    }
                }

                if (animalQueryMenuQuery != toSpeak)
                {
                    animalQueryMenuQuery = toSpeak;
                    MainClass.ScreenReader.Say($"{details} {toSpeak}", true);
                }
            }
            catch (System.Exception e)
            {
                MainClass.ErrorLog($"Unable to narrate Text:\n{e.Message}\n{e.StackTrace}");
            }
        }