public CustomBobberBar(SFarmer user, int whichFish, float fishSize, bool treasure, int bobber, int waterDepth) : base(whichFish, fishSize, treasure, bobber)
        {
            this.User        = user;
            this._origStreak = FishHelper.GetStreak(user);

            /* Private field hooks */
            this._treasureField            = ModFishing.INSTANCE.Helper.Reflection.GetPrivateField <bool>(this, "treasure");
            this._treasureCaughtField      = ModFishing.INSTANCE.Helper.Reflection.GetPrivateField <bool>(this, "treasureCaught");
            this._treasurePositionField    = ModFishing.INSTANCE.Helper.Reflection.GetPrivateField <float>(this, "treasurePosition");
            this._treasureAppearTimerField = ModFishing.INSTANCE.Helper.Reflection.GetPrivateField <float>(this, "treasureAppearTimer");
            this._treasureScaleField       = ModFishing.INSTANCE.Helper.Reflection.GetPrivateField <float>(this, "treasureScale");

            this._distanceFromCatchingField = ModFishing.INSTANCE.Helper.Reflection.GetPrivateField <float>(this, "distanceFromCatching");
            this._treasureCatchLevelField   = ModFishing.INSTANCE.Helper.Reflection.GetPrivateField <float>(this, "treasureCatchLevel");

            this._bobberBarPosField = ModFishing.INSTANCE.Helper.Reflection.GetPrivateField <float>(this, "bobberBarPos");
            this._difficultyField   = ModFishing.INSTANCE.Helper.Reflection.GetPrivateField <float>(this, "difficulty");
            this._fishQualityField  = ModFishing.INSTANCE.Helper.Reflection.GetPrivateField <int>(this, "fishQuality");
            this._perfectField      = ModFishing.INSTANCE.Helper.Reflection.GetPrivateField <bool>(this, "perfect");

            this._sparkleTextField = ModFishing.INSTANCE.Helper.Reflection.GetPrivateField <SparklingText>(this, "sparkleText");

            this._lastDistanceFromCatching = this._distanceFromCatchingField.GetValue();
            this._lastTreasureCatchLevel   = this._treasureCatchLevelField.GetValue();

            /* Actual code */
            ConfigMain    config  = ModFishing.INSTANCE.Config;
            ConfigStrings strings = ModFishing.INSTANCE.Strings;

            // Choose a random fish, this time using the custom fish selector
            FishingRod rod = Game1.player.CurrentTool as FishingRod;
            //int waterDepth = rod != null ? ModEntry.INSTANCE.Helper.Reflection.GetPrivateValue<int>(rod, "clearWaterDistance") : 0;

            // Applies difficulty modifier, including if fish isn't paying attention
            float difficulty = this._difficultyField.GetValue() * config.BaseDifficultyMult;

            difficulty *= 1f + config.DifficultyStreakEffect * this._origStreak;
            double difficultyChance = config.UnawareChance + user.LuckLevel * config.UnawareLuckLevelEffect + Game1.dailyLuck * config.UnawareDailyLuckEffect;

            if (Game1.random.NextDouble() < difficultyChance)
            {
                Game1.showGlobalMessage(string.Format(strings.UnawareFish, 1f - config.UnawareMult));
                difficulty *= config.UnawareMult;
            }
            this._difficultyField.SetValue(difficulty);

            // Adjusts quality to be increased by streak
            int fishQuality = this._fishQualityField.GetValue();

            this._origQuality = fishQuality;
            int qualityBonus = (int)Math.Floor((double)this._origStreak / config.StreakForIncreasedQuality);

            fishQuality = Math.Min(fishQuality + qualityBonus, 3);
            if (fishQuality == 3)
            {
                fishQuality++;                   // Iridium-quality fish. Only possible through your perfect streak
            }
            this._fishQualityField.SetValue(fishQuality);

            // Increase the user's perfect streak (this will be dropped to 0 if they don't get a perfect catch)
            if (this._origStreak >= config.StreakForIncreasedQuality)
            {
                this._sparkleTextField.SetValue(new SparklingText(Game1.dialogueFont, string.Format(strings.StreakDisplay, this._origStreak), Color.Yellow, Color.White));
            }
            FishHelper.SetStreak(user, this._origStreak + 1);
        }
        public override void update(GameTime time)
        {
            // Speed warp on normal catching
            float distanceFromCatching = this._distanceFromCatchingField.GetValue();
            float delta = distanceFromCatching - this._lastDistanceFromCatching;

            distanceFromCatching          += (ModFishing.INSTANCE.Config.CatchSpeed - 1f) * delta;
            this._lastDistanceFromCatching = distanceFromCatching;
            this._distanceFromCatchingField.SetValue(distanceFromCatching);

            // Speed warp on treasure catching
            float treasureCatchLevel = this._treasureCatchLevelField.GetValue();

            delta = treasureCatchLevel - this._lastTreasureCatchLevel;
            treasureCatchLevel          += (ModFishing.INSTANCE.Config.TreasureCatchSpeed - 1f) * delta;
            this._lastTreasureCatchLevel = treasureCatchLevel;
            this._treasureCatchLevelField.SetValue(treasureCatchLevel);

            bool perfect        = this._perfectField.GetValue();
            bool treasure       = this._treasureField.GetValue();
            bool treasureCaught = this._treasureCaughtField.GetValue();

            ConfigStrings strings = ModFishing.INSTANCE.Strings;

            // Check if still perfect, otherwise apply changes to loot
            if (!this._perfectChanged && !perfect)
            {
                this._perfectChanged = true;
                this._fishQualityField.SetValue(Math.Min(this._origQuality, 1));
                FishHelper.SetStreak(this.User, 0);
                if (this._origStreak >= ModFishing.INSTANCE.Config.StreakForIncreasedQuality)
                {
                    Game1.showGlobalMessage(treasure ? string.Format(strings.WarnStreak, this._origStreak) : string.Format(strings.LostStreak, this._origStreak));
                }
            }

            if (!this._treasureChanged && !perfect && treasure && treasureCaught)
            {
                this._treasureChanged = true;
                int qualityBonus = (int)Math.Floor((double)this._origStreak / ModFishing.INSTANCE.Config.StreakForIncreasedQuality);
                int quality      = this._origQuality;
                quality = Math.Min(quality + qualityBonus, 3);
                if (quality == 3)
                {
                    quality++;
                }
                this._fishQualityField.SetValue(quality);
            }

            base.update(time);

            distanceFromCatching = this._distanceFromCatchingField.GetValue();

            if (distanceFromCatching <= 0.0)
            {
                // Failed to catch fish
                //FishHelper.setStreak(this.user, 0);
                if (!this._notifiedFailOrSucceed && treasure)
                {
                    this._notifiedFailOrSucceed = true;
                    if (this._origStreak >= ModFishing.INSTANCE.Config.StreakForIncreasedQuality)
                    {
                        Game1.showGlobalMessage(string.Format(strings.LostStreak, this._origStreak));
                    }
                }
            }
            else if (distanceFromCatching >= 1.0)
            {
                // Succeeded in catching the fish
                if (!this._notifiedFailOrSucceed && !perfect && treasure && treasureCaught)
                {
                    this._notifiedFailOrSucceed = true;
                    if (this._origStreak >= ModFishing.INSTANCE.Config.StreakForIncreasedQuality)
                    {
                        Game1.showGlobalMessage(string.Format(strings.KeptStreak, this._origStreak));
                    }
                    FishHelper.SetStreak(this.User, this._origStreak);
                }
            }
        }
예제 #3
0
        public static void OpenTreasureMenuEndFunction(FishingRod rod, int extra)
        {
            ModFishing.INSTANCE.Monitor.Log("Successfully replaced treasure", LogLevel.Trace);

            ConfigMain config             = ModFishing.INSTANCE.Config;
            SFarmer    lastUser           = ModFishing.INSTANCE.Helper.Reflection.GetPrivateValue <SFarmer>(rod, "lastUser");
            int        clearWaterDistance = 5;

            if (config.OverrideFishing)
            {
                if (FishingRodOverrides.ClearWaterDistances.ContainsKey(lastUser))
                {
                    clearWaterDistance = FishingRodOverrides.ClearWaterDistances[lastUser];
                }
                else
                {
                    ModFishing.INSTANCE.Monitor.Log("The bobber bar was not replaced. Fishing might not be overridden by this mod", LogLevel.Warn);
                }
            }
            int whichFish   = ModFishing.INSTANCE.Helper.Reflection.GetPrivateValue <int>(rod, "whichFish");
            int fishQuality = ModFishing.INSTANCE.Helper.Reflection.GetPrivateValue <int>(rod, "fishQuality");

            lastUser.gainExperience(5, 10 * (clearWaterDistance + 1));
            rod.doneFishing(lastUser, true);
            lastUser.completelyStopAnimatingOrDoingAction();

            // REWARDS
            List <Item> rewards = new List <Item>();

            if (extra == 1)
            {
                rewards.Add(new StardewValley.Object(whichFish, 1, false, -1, fishQuality));
            }

            List <TreasureData> possibleLoot = new List <TreasureData>(config.PossibleLoot)
                                               .Where(treasure => treasure.IsValid(lastUser.FishingLevel, clearWaterDistance)).ToList();

            // Select rewards
            float chance = 1f;
            int   streak = FishHelper.GetStreak(lastUser);

            while (possibleLoot.Count > 0 && rewards.Count < config.MaxTreasureQuantity && Game1.random.NextDouble() <= chance)
            {
                TreasureData treasure = possibleLoot.Choose(Game1.random);

                int id = treasure.id + Game1.random.Next(treasure.idRange - 1);

                if (id == Objects.LOST_BOOK)
                {
                    if (lastUser.archaeologyFound == null || !lastUser.archaeologyFound.ContainsKey(102) || lastUser.archaeologyFound[102][0] >= 21)
                    {
                        continue;
                    }
                    Game1.showGlobalMessage("You found a lost book. The library has been expanded.");
                }

                int count = Game1.random.Next(treasure.minAmount, treasure.maxAmount);

                Item reward;
                if (treasure.meleeWeapon)
                {
                    reward = new MeleeWeapon(id);
                }
                else if (id >= Ring.ringLowerIndexRange && id <= Ring.ringUpperIndexRange)
                {
                    reward = new Ring(id);
                }
                else if (id >= 504 && id <= 513)
                {
                    reward = new Boots(id);
                }
                else
                {
                    reward = new StardewValley.Object(Vector2.Zero, id, count);
                }

                rewards.Add(reward);
                if (!config.AllowDuplicateLoot || !treasure.allowDuplicates)
                {
                    possibleLoot.Remove(treasure);
                }

                //rewards.Add(new StardewValley.Object(Vector2.Zero, Objects.BAIT, Game1.random.Next(10, 25)));
            }

            // Add bait if no rewards were selected. NOTE: This should never happen
            if (rewards.Count == 0)
            {
                ModFishing.INSTANCE.Monitor.Log("Could not find any valid loot for the treasure chest. Check your treasure.json?", LogLevel.Warn);
                rewards.Add(new StardewValley.Object(685, Game1.random.Next(2, 5) * 5, false, -1, 0));
            }

            // Show rewards GUI
            Game1.activeClickableMenu = new ItemGrabMenu(rewards);
            (Game1.activeClickableMenu as ItemGrabMenu).source = 3;
            lastUser.completelyStopAnimatingOrDoingAction();
        }
예제 #4
0
 public static int GetRandomFish(int depth, int mineLevel = -1) => FishHelper.GetRandomFish(FishHelper.GetPossibleFish(depth, mineLevel));
예제 #5
0
        public static void StartMinigameEndFunction(FishingRod rod, int extra)
        {
            ModFishing.INSTANCE.Monitor.Log("Overriding fishing minigame", LogLevel.Trace);
            ConfigMain config   = ModFishing.INSTANCE.Config;
            SFarmer    lastUser = ModFishing.INSTANCE.Helper.Reflection.GetPrivateValue <SFarmer>(rod, "lastUser");
            Vector2    bobber   = ModFishing.INSTANCE.Helper.Reflection.GetPrivateValue <Vector2>(rod, "bobber");

            rod.isReeling = true;
            rod.hit       = false;
            switch (lastUser.FacingDirection)
            {
            case 1:
                lastUser.FarmerSprite.setCurrentSingleFrame(48, 32000, false, false);
                break;

            case 3:
                lastUser.FarmerSprite.setCurrentSingleFrame(48, 32000, false, true);
                break;
            }
            lastUser.FarmerSprite.pauseForSingleAnimation = true;

            int clearWaterDistance = FishingRod.distanceToLand((int)(bobber.X / (double)Game1.tileSize - 1.0), (int)(bobber.Y / (double)Game1.tileSize - 1.0), lastUser.currentLocation);

            FishingRodOverrides.ClearWaterDistances[lastUser] = clearWaterDistance;
            float num = 1f * (clearWaterDistance / 5f) * (Game1.random.Next(1 + Math.Min(10, lastUser.FishingLevel) / 2, 6) / 5f);

            if (rod.favBait)
            {
                num *= 1.2f;
            }
            float fishSize = Math.Max(0.0f, Math.Min(1f, num * (float)(1.0 + Game1.random.Next(-10, 10) / 100.0)));
            bool  treasure = false;

            double treasureChance = config.TreasureChance + lastUser.LuckLevel * config.TreasureLuckLevelEffect + (rod.getBaitAttachmentIndex() == 703 ? config.TreasureBaitEffect : 0.0) + (rod.getBobberAttachmentIndex() == 693 ? config.TreasureBobberEffect : 0.0) + Game1.dailyLuck * config.TreasureDailyLuckEffect + (lastUser.professions.Contains(9) ? config.TreasureChance : 0.0) + config.TreasureStreakEffect * FishHelper.GetStreak(lastUser);

            treasureChance = Math.Min(treasureChance, config.MaxTreasureChance);
            if (!Game1.isFestival() && lastUser.fishCaught != null && lastUser.fishCaught.Count > 1 && Game1.random.NextDouble() < treasureChance)
            {
                treasure = true;
            }

            // Override caught fish
            bool legendary = FishHelper.IsLegendary(extra);

            if (!config.UseVanillaFish && (!config.VanillaLegendaries || !legendary))
            {
                int origExtra = extra;
                extra = FishHelper.GetRandomFish(clearWaterDistance);
                if (FishHelper.IsTrash(extra))
                {
                    if (false) // TODO: Replace this with code relating to a config option that determines the chance you'll get fish/trash
                    {
#pragma warning disable CS0162 // Unreachable code detected
                        Game1.showGlobalMessage("No valid fish to catch! Giving junk instead.");
                        StardewValley.Object o = new StardewValley.Object(extra, 1, false, -1, 0);
                        rod.pullFishFromWater(extra, -1, 0, 0, false, false);
                        return;

#pragma warning restore CS0162 // Unreachable code detected
                    }
                    else
                    {
                        ModFishing.INSTANCE.Monitor.Log("No valid fish to catch! Using original fish instead.", LogLevel.Warn);
                        extra = origExtra;
                    }
                }
            }

            // Show custom bobber bar
            Game1.activeClickableMenu = new CustomBobberBar(lastUser, extra, fishSize, treasure, rod.attachments[1] != null ? rod.attachments[1].ParentSheetIndex : -1, clearWaterDistance);
        }