예제 #1
0
        /// <summary>
        /// Update mod state.  Try to keep processing quick here.
        /// </summary>
        public void OnUpdate()
        {
            if (!(Game1.player.CurrentTool is FishingRod))
            {
                return;
            }

            FishingRod currentTool = Game1.player.CurrentTool as FishingRod;

            // Could set up a state machine to track this, but for now just check either in the minigame or not.
            if (Game1.activeClickableMenu is BobberBar && currentTool.isFishing)
            {
                PlayFishMinigame();
            }
            else
            {
                // Do everything else the mod does outside of the fishing game.
                // If this is the first time out of the fishing game, clear the data.
                if (this.inFishingMenu)
                {
                    log.Silly("Left Fishing minigame, clearing memory");
                    this.UnloadSVReflectionObjects();
                    this.inFishingMenu            = false;
                    IsButtonDownHack.simulateDown = false;
                }

                // This might be where a state machine might help, as an extra check, (e.g can't set power if you're not done casting, etc...)
                // but the SV tool API seems to give us enough data to have a go at it just checking conditionals.

                // Sequential steps to automate fishing
                if (config.autoCast && ShouldDoAutoCast(currentTool))
                {
                    log.Trace("Attempting to cast for the user");
                    currentTool.beginUsing(Game1.currentLocation,
                                           Game1.player.getStandingX(),
                                           Game1.player.getStandingY(),
                                           Game1.player);
                }

                if (config.maxCastPower && ShouldSetCastingPower(currentTool))
                {
                    log.Trace("Modifying cast to max cast power");
                    // Apparently for max to be registered it needs to be > 1.0, but anything over increases the
                    // power bar past the UI, so make it a small number.  Also, 1.001F is too small.
                    currentTool.castingPower = 1.01F;
                }

                if (config.quickHook && ShouldSetQuickHook(currentTool))
                {
                    log.Trace("Modifying cast so fish will bite quickly.");
                    // Game uses fishingBiteAccumulator as the value that gets modified so we should only modify that one
                    // and let the game increase it and handle logic as they become equal.  Change the gap if it doesn't
                    // generate a quick hit quick enough.
                    currentTool.fishingBiteAccumulator = currentTool.timeUntilFishingBite - fishingBiteAccumulatorGap;
                }

                if (config.autoHook && ShouldDoAutoHook(currentTool))
                {
                    log.Trace("Executing hook function for FishingRod");
                    currentTool.DoFunction(Game1.currentLocation,
                                           Game1.player.getStandingX(),
                                           Game1.player.getStandingY(),
                                           (int)currentTool.castingPower,
                                           Game1.player);
                }

                // Click away the catched fish.  The conditionals are ordered here in a way
                // the check for the popup happens before the config check so the code can
                // always check the treasure chest.  See the variable doneCaughtFish for more
                // info.
                if (ShouldDoDismissCaughtPopup(currentTool))
                {
                    log.Trace("Tool is sitting at caught fish popup");
                    doneCaughtFish = true;

                    if (config.autoFinish && config.HarmonyLoad)
                    {
                        log.Trace("Closing popup with Harmony");
                        ClickAtAllHack.simulateClick = true;
                    }
                }
                else
                {
                    if (ClickAtAllHack.simulateClick)
                    {
                        log.Trace("Turning off Harmony injection for caught fish popup");
                        ClickAtAllHack.simulateClick = false;
                    }
                }

                // Deal with any treasure that has popped up
                if (ShouldDoProcessTreasure(currentTool) && doneCaughtFish)
                {
                    log.Trace("Found treasure after the caught fish popup");
                    doneCaughtFish = false;
                    if (config.autoFinish)
                    {
                        log.Trace("Acquiring treasure");
                        ItemGrabMenu m = Game1.activeClickableMenu as ItemGrabMenu;
                        if (m.ItemsToGrabMenu != null && m.ItemsToGrabMenu.actualInventory != null)
                        {
                            if (AcquireTreasure(m.ItemsToGrabMenu.actualInventory))
                            {
                                m.exitThisMenu(true);
                            }
                            else
                            {
                                HandleItemGrabMenuError(m, "might be full inventory");
                            }
                        }
                        else
                        {
                            HandleItemGrabMenuError(m, "treasure chest is open, but inventory is null");
                        }
                    }
                }
            }
        }
예제 #2
0
        private void OnUpdateTicked(object sender, UpdateTickedEventArgs args)
        {
            Farmer player = Game1.player;


            // freeze time
            Game1.gameTimeInterval = 0;

            // infinite stamina
            player.stamina = player.MaxStamina;



            if (player == null || !player.IsLocalPlayer)
            {
                return;
            }
            if (!(Game1.player.CurrentTool is FishingRod))
            {
                return;
            }



            FishingRod rod = Game1.player.CurrentTool as FishingRod;



            if (autoCastRod & ShouldDoAutoCast(rod))
            {
                rod.beginUsing(Game1.currentLocation,
                               Game1.player.getStandingX(),
                               Game1.player.getStandingY(),
                               Game1.player);
            }


            if (rod.isTimingCast)
            {
                rod.castingTimerSpeed = 0;
                rod.castingPower      = 1;
            }

            if (!rod.isNibbling && rod.isFishing && !rod.isReeling && !rod.pullingOutOfWater && !rod.hit)
            {
                rod.timeUntilFishingBite = 0;
            }

            if (rod.isNibbling && rod.isFishing && !rod.isReeling && !rod.pullingOutOfWater && !rod.hit)
            {
                Farmer.useTool(player);
            }

            // Click away the catched fish.  The conditionals are ordered here in a way
            // the check for the popup happens before the config check so the code can
            // always check the treasure chest.  See the variable doneCaughtFish for more
            // info.
            if (ShouldDoDismissCaughtPopup(rod))
            {
                log.Trace("Tool is sitting at caught fish popup");



                log.Trace("Closing popup with Harmony");
                ClickAtAllHack.simulateClick = true;
            }



            // 6x per second


            if (args.IsMultipleOf(10))
            {
                IsButtonDownHack.simulateDown = false;

                if (Game1.activeClickableMenu is BobberBar bar)
                {
                    int best_action;

                    double diffBobberFish = bobberPosition - bobberBarPos;

                    double[] OldState = new double[] { (double)bobberBarPos, (double)bobberPosition, (double)bobberBarSpeed, (double)distanceFromCatching };

                    // if is the first iteration StateBuffer don't have anything
                    if (CountFishes == 0)
                    {
                        StateBuffer = OldState;
                    }


                    // Update State
                    bobberBarPos         = Helper.Reflection.GetField <float>(bar, "bobberBarPos").GetValue();
                    bobberBarSpeed       = Helper.Reflection.GetField <float>(bar, "bobberBarSpeed").GetValue();
                    bobberPosition       = Helper.Reflection.GetField <float>(bar, "bobberPosition").GetValue();
                    distanceFromCatching = Helper.Reflection.GetField <float>(bar, "distanceFromCatching").GetValue();


                    diffBobberFish = bobberPosition - bobberBarPos;

                    double [] NewState = new double[] { (double)bobberBarPos, (double)bobberPosition, (double)bobberBarSpeed, (double)distanceFromCatching };


                    int rand = rnd.Next(100);

                    best_action = (int)Agent.Update(StateBuffer, OldState, NewState);

                    if (rand < 5)
                    {
                        rand = 0;
                        // explore random action and it's outcome
                        //best_action = rnd.Next(1);
                    }



                    // execute action if needed
                    if (best_action == 1)
                    {
                        IsButtonDownHack.simulateDown = true;
                    }
                    else
                    {
                        // do NOTHING
                        //IsButtonDownHack.simulateDown = false;
                    }


                    // store last state

                    StateBuffer = OldState;
                }
            }
        }