public static void CollectFish(Farmer who, FishingRod rod) { IReflectedField <int> recastTimerMs = Reflection.GetField <int>(rod, "recastTimerMs"); int whichFish = Reflection.GetField <int>(rod, "whichFish").GetValue(); int fishQuality = Reflection.GetField <int>(rod, "fishQuality").GetValue(); string itemCategory = Reflection.GetField <string>(rod, "itemCategory").GetValue(); if (!Game1.isFestival()) { who.faceDirection(2); who.FarmerSprite.setCurrentFrame(84); } if (Game1.random.NextDouble() < 0.025) { who.currentLocation.temporarySprites.Add(new TemporaryAnimatedSprite("LooseSprites\\Cursors", new Rectangle(653, 858, 1, 1), 9999f, 1, 1, who.Position + new Vector2(Game1.random.Next(-3, 2) * 4, -32f), false, false, (float)(who.getStandingY() / 10000.0 + 1.0 / 500.0), 0.04f, Color.LightBlue, 5f, 0.0f, 0.0f, 0.0f) { acceleration = new Vector2(0.0f, 0.25f) }); } if (!who.IsLocalPlayer) { return; } who.currentLocation.localSound("coin"); if (!rod.treasureCaught) { recastTimerMs.SetValue(200); Object @object = null; switch (itemCategory) { case "Object": { @object = new Object(whichFish, 1, false, -1, fishQuality); if (whichFish == GameLocation.CAROLINES_NECKLACE_ITEM) { @object.questItem.Value = true; } if (whichFish == 79 || whichFish == 842) { @object = who.currentLocation.tryToCreateUnseenSecretNote(who); if (@object == null) { return; } } if (rod.caughtDoubleFish) { @object.Stack = 2; } break; } case "Furniture": { @object = new Furniture(whichFish, Vector2.Zero); break; } } bool fromFishPond = rod.fromFishPond; who.completelyStopAnimatingOrDoingAction(); rod.doneFishing(who, !fromFishPond); if (!Game1.isFestival() && !fromFishPond && (itemCategory == "Object" && Game1.player.team.specialOrders != null)) { foreach (SpecialOrder specialOrder in Game1.player.team.specialOrders) { specialOrder.onFishCaught?.Invoke(Game1.player, @object); } } if (Game1.isFestival() || who.addItemToInventoryBool(@object)) { return; } Game1.activeClickableMenu = new ItemGrabMenu(new List <Item> { @object }, rod).setEssential(true); } else { rod.fishCaught = false; rod.showingTreasure = true; who.UsingTool = true; int initialStack = 1; if (rod.caughtDoubleFish) { initialStack = 2; } Object @object = new Object(whichFish, initialStack, false, -1, fishQuality); if (Game1.player.team.specialOrders != null) { foreach (SpecialOrder specialOrder in Game1.player.team.specialOrders) { specialOrder.onFishCaught?.Invoke(Game1.player, @object); } } bool inventoryBool = who.addItemToInventoryBool(@object); rod.animations.Add(new TemporaryAnimatedSprite("LooseSprites\\Cursors", new Rectangle(64, 1920, 32, 32), 500f, 1, 0, who.Position + new Vector2(-32f, -160f), false, false, (float)(who.getStandingY() / 10000.0 + 1.0 / 1000.0), 0.0f, Color.White, 4f, 0.0f, 0.0f, 0.0f) { motion = new Vector2(0.0f, -0.128f), timeBasedMotion = true, endFunction = rod.openChestEndFunction, extraInfoForEndBehavior = inventoryBool ? 0 : 1, alpha = 0.0f, alphaFade = -1f / 500f }); } }
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(); }
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(); }