public static float GetRawTreasureChance(SFarmer who, FishingRod rod) { ConfigMain.ConfigGlobalTreasure config = ModFishing.Instance.MainConfig.GlobalTreasureSettings; // Calculate chance float chance = config.TreasureChance; chance += who.LuckLevel * config.TreasureLuckLevelEffect; chance += (float)Game1.dailyLuck * config.TreasureDailyLuckEffect; chance += config.TreasureStreakEffect * ModFishing.Instance.Api.GetStreak(who); if (rod.getBaitAttachmentIndex() == 703) { chance += config.TreasureBaitEffect; } if (rod.getBobberAttachmentIndex() == 693) { chance += config.TreasureBobberEffect; } if (who.professions.Contains(9)) { chance += config.TreasureChance; } return(Math.Min(chance, config.MaxTreasureChance)); }
private void OpenTreasureEndFunction(FishingRod rod, Farmer user, int includeFish) { ModFishing.Instance.Monitor.Log("Successfully replaced treasure", LogLevel.Trace); ConfigMain.ConfigGlobalTreasure config = ModFishing.Instance.MainConfig.GlobalTreasureSettings; int clearWaterDistance = ModFishing.Instance.Helper.Reflection.GetField <int>(rod, "clearWaterDistance")?.GetValue() ?? 5; int whichFish = ModFishing.Instance.Helper.Reflection.GetField <int>(rod, "whichFish").GetValue(); int fishQuality = ModFishing.Instance.Helper.Reflection.GetField <int>(rod, "fishQuality").GetValue(); // Gain experience and call vanilla code for this user.gainExperience(5, 10 * (clearWaterDistance + 1)); rod.doneFishing(user, true); user.completelyStopAnimatingOrDoingAction(); // REWARDS List <Item> rewards = new List <Item>(); if (includeFish == 1) { rewards.Add(new SObject(whichFish, 1, false, -1, fishQuality)); } List <ITreasureData> possibleLoot = new List <ITreasureData>(ModFishing.Instance.TreasureConfig.PossibleLoot) .Where(treasure => treasure.IsValid(user)).ToList(); // Select rewards float chance = 1f; int streak = ModFishing.Instance.Api.GetStreak(user); while (possibleLoot.Count > 0 && rewards.Count < config.MaxTreasureQuantity && Game1.random.NextDouble() <= chance) { ITreasureData treasure = possibleLoot.Choose(Game1.random); // Choose an ID for the treasure IList <int> ids = treasure.PossibleIds(); int id = ids[Game1.random.Next(ids.Count)]; // Lost books have custom handling if (id == Objects.LostBook) { if (user.archaeologyFound == null || !user.archaeologyFound.ContainsKey(102) || user.archaeologyFound[102][0] >= 21) { possibleLoot.Remove(treasure); continue; } Game1.showGlobalMessage("You found a lost book. The library has been expanded."); } // Create reward item 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 { // Random quantity int count = Game1.random.Next(treasure.MinAmount, treasure.MaxAmount); reward = new SObject(Vector2.Zero, id, count); } // Add the reward rewards.Add(reward); // Check if this reward shouldn't be duplicated if (!config.AllowDuplicateLoot || !treasure.AllowDuplicates) { possibleLoot.Remove(treasure); } // Update chance chance *= config.AdditionalLootChance + streak * config.StreakAdditionalLootChance; } // 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 SObject(685, Game1.random.Next(2, 5) * 5)); } // Show rewards GUI ModFishing.Instance.Monitor.Log($"Treasure rewards: {string.Join(", ", rewards)}", LogLevel.Trace); Game1.activeClickableMenu = new ItemGrabMenu(rewards); ((ItemGrabMenu)Game1.activeClickableMenu).source = 3; user.completelyStopAnimatingOrDoingAction(); }