Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of FishTracker v1.1.0
FishTracker.dll
Decompiled a day agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Koendertjh.Shared; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("FishTracker")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.1.0.0")] [assembly: AssemblyInformationalVersion("1.1.0+f7ba504173c8baf3016192861cacfb2a4bba9570")] [assembly: AssemblyProduct("FishTracker")] [assembly: AssemblyTitle("FishTracker")] [assembly: AssemblyVersion("1.1.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Koendertjh.Shared { internal static class AchievementStats { private static readonly Dictionary<object, KeyValuePair<int, HashSet<string>>> s_keys = new Dictionary<object, KeyValuePair<int, HashSet<string>>>(); internal static Achievement Find(string id) { if ((Object)(object)Achievements.m_instance == (Object)null) { return null; } foreach (AchievementList achievementList in Achievements.m_instance.m_achievementLists) { foreach (Achievement achievement in achievementList.m_achievements) { if ((Object)(object)achievement != (Object)null && achievement.m_id == id) { return achievement; } } } return null; } internal static PlayerStats StatsFor(Achievement achievement) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) Game instance = Game.instance; PlayerProfile val = ((instance != null) ? instance.GetPlayerProfile() : null); if (val == null || (Object)(object)achievement == (Object)null) { return null; } return val.m_playerStats[achievement.m_difficultyRequirement]; } internal static HashSet<string> Keys(List<DictStatRequirement> triggers) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) if (triggers == null) { return new HashSet<string>(); } if (s_keys.TryGetValue(triggers, out var value) && value.Key == triggers.Count) { return value.Value; } HashSet<string> hashSet = new HashSet<string>(); foreach (DictStatRequirement trigger in triggers) { hashSet.Add(trigger.m_stat); } s_keys[triggers] = new KeyValuePair<int, HashSet<string>>(triggers.Count, hashSet); return hashSet; } internal static HashSet<string> Keys(List<EnemyStatRequirement> triggers) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) if (triggers == null) { return new HashSet<string>(); } if (s_keys.TryGetValue(triggers, out var value) && value.Key == triggers.Count) { return value.Value; } HashSet<string> hashSet = new HashSet<string>(); foreach (EnemyStatRequirement trigger in triggers) { hashSet.Add(trigger.m_stat); } s_keys[triggers] = new KeyValuePair<int, HashSet<string>>(triggers.Count, hashSet); return hashSet; } internal static bool Has(Dictionary<string, float> stats, string key) { if (stats != null && stats.TryGetValue(key, out var value)) { return value >= 1f; } return false; } internal static int CountDone(HashSet<string> keys, Dictionary<string, float> stats) { int num = 0; foreach (string key in keys) { if (Has(stats, key)) { num++; } } return num; } } } namespace FishTracker { [HarmonyPatch] internal static class Chum { private const string PrefabPrefix = "Chum_"; private const string TetraPrefab = "Fish4_cave"; private static GameObject s_holder; private static readonly Dictionary<GameObject, GameObject> s_chums = new Dictionary<GameObject, GameObject>(); private static readonly Dictionary<string, string> s_baitOf = new Dictionary<string, string>(); private static readonly List<Recipe> s_recipes = new List<Recipe>(); internal static string BaitOf(string chumName) { if (!s_baitOf.TryGetValue(chumName, out var value)) { return null; } return value; } [HarmonyPrefix] [HarmonyPatch(typeof(ObjectDB), "Awake")] private static void ObjectDBAwake(ObjectDB __instance) { AddToObjectDB(__instance); } [HarmonyPostfix] [HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")] private static void ObjectDBCopy(ObjectDB __instance) { if (AddToObjectDB(__instance)) { AccessTools.Method(typeof(ObjectDB), "UpdateRegisters", (Type[])null, (Type[])null).Invoke(__instance, null); } } [HarmonyPrefix] [HarmonyPatch(typeof(ZNetScene), "Awake")] private static void ZNetSceneAwake(ZNetScene __instance) { if (!FishTrackerPlugin.ChumEnabled.Value) { return; } CreateChums(__instance.m_prefabs); foreach (GameObject key in s_chums.Keys) { if (!__instance.m_prefabs.Contains(key)) { __instance.m_prefabs.Add(key); } } } private static bool AddToObjectDB(ObjectDB db) { if (!FishTrackerPlugin.ChumEnabled.Value || db.m_items == null || db.m_items.Count == 0) { return false; } CreateChums(db.m_items); bool result = false; foreach (GameObject key in s_chums.Keys) { if (!db.m_items.Contains(key)) { db.m_items.Add(key); result = true; } } foreach (Recipe s_recipe in s_recipes) { if (!db.m_recipes.Contains(s_recipe)) { db.m_recipes.Add(s_recipe); } } return result; } private static void CreateChums(List<GameObject> prefabs) { //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Expected O, but got Unknown //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Expected O, but got Unknown if ((Object)(object)s_holder != (Object)null) { return; } List<GameObject> list = new List<GameObject>(); foreach (GameObject prefab in prefabs) { Fish val = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<Fish>() : null); if ((Object)(object)val == (Object)null) { continue; } foreach (BaitSetting bait in val.m_baits) { if ((Object)(object)bait.m_bait != (Object)null && !list.Contains(((Component)bait.m_bait).gameObject)) { list.Add(((Component)bait.m_bait).gameObject); } } } if (list.Count == 0) { return; } s_holder = new GameObject("FishTracker_Chum"); s_holder.SetActive(false); Object.DontDestroyOnLoad((Object)(object)s_holder); foreach (GameObject item in list) { GameObject val2 = Object.Instantiate<GameObject>(item, s_holder.transform); ((Object)val2).name = "Chum_" + ((Object)item).name; SharedData shared = item.GetComponent<ItemDrop>().m_itemData.m_shared; SharedData shared2 = val2.GetComponent<ItemDrop>().m_itemData.m_shared; shared2.m_name = ChumName(shared.m_name); shared2.m_description = "Bait, mashed up and ready to throw into the water. Use it while facing the water and the fish that take this bait come to you."; shared2.m_itemType = (ItemType)1; shared2.m_ammoType = ""; shared2.m_maxStackSize = 20; s_chums[val2] = item; s_baitOf[shared2.m_name] = shared.m_name; Recipe val3 = ScriptableObject.CreateInstance<Recipe>(); ((Object)val3).name = "Recipe_" + ((Object)val2).name; val3.m_item = val2.GetComponent<ItemDrop>(); val3.m_amount = 1; val3.m_enabled = true; val3.m_minStationLevel = 1; val3.m_resources = (Requirement[])(object)new Requirement[1] { new Requirement { m_resItem = item.GetComponent<ItemDrop>(), m_amount = FishTrackerPlugin.BaitPerChum.Value, m_recover = true } }; s_recipes.Add(val3); } FishTrackerPlugin.Log.LogInfo((object)$"Added {s_chums.Count} kinds of chum."); } private static string ChumName(string baitName) { string text = ((Localization.instance != null) ? Localization.instance.Localize(baitName) : baitName); if (text.StartsWith("$")) { return "Chum"; } if (!text.Contains("Fishing Bait")) { return text + " Chum"; } return text.Replace("Fishing Bait", "Chum"); } [HarmonyPrefix] [HarmonyPatch(typeof(Humanoid), "UseItem")] private static bool UseItem(Humanoid __instance, Inventory inventory, ItemData item) { if (item?.m_shared == null || !s_baitOf.TryGetValue(item.m_shared.m_name, out var value) || (Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return true; } Player localPlayer = Player.m_localPlayer; if (inventory == null) { inventory = ((Humanoid)localPlayer).GetInventory(); } if (TrySpawnFish(localPlayer, value)) { inventory.RemoveOneItem(item); } return false; } private static bool TrySpawnFish(Player player, string bait) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) if (!FindWater(player, out var point, out var waterLevel)) { ((Character)player).Message((MessageType)2, "Face deeper water to throw the chum in.", 0, (Sprite)null, false); return false; } Biome biome = WorldGenerator.instance.GetBiome(point); List<FishInfo> list = new List<FishInfo>(); foreach (FishInfo item in FishData.All) { if (item.Baits.ContainsKey(bait) && LivesIn(item, biome)) { list.Add(item); } } if (list.Count == 0) { ((Character)player).Message((MessageType)2, "No fish here take this chum. Try another biome.", 0, (Sprite)null, false); return false; } Vector3 val2 = default(Vector3); for (int i = 0; i < FishTrackerPlugin.FishPerChum.Value; i++) { FishInfo fishInfo = Pick(list, bait); Vector2 val = Random.insideUnitCircle * 3f; ((Vector3)(ref val2))..ctor(point.x + val.x, waterLevel - 1f, point.z + val.y); GameObject val3 = Object.Instantiate<GameObject>(fishInfo.Prefab, val2, Quaternion.Euler(0f, Random.Range(0f, 360f), 0f)); int num = RollLevel(); if (num > 1) { ItemDrop component = val3.GetComponent<ItemDrop>(); if (component != null) { component.SetQuality(num); } } } ((Character)player).Message((MessageType)2, "The water stirs...", 0, (Sprite)null, false); return true; } private static bool LivesIn(FishInfo fish, Biome biome) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Invalid comparison between Unknown and I4 if ((fish.Biomes & biome) == 0) { if ((int)biome == 64 && FishTrackerPlugin.TetraInDeepNorth.Value) { return ((Object)fish.Prefab).name == "Fish4_cave"; } return false; } return true; } private static bool FindWater(Player player, out Vector3 point, out float waterLevel) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) Vector3 forward = ((Component)player).transform.forward; forward.y = 0f; ((Vector3)(ref forward)).Normalize(); for (float num = 4f; num <= 14f; num += 2f) { point = ((Component)player).transform.position + forward * num; waterLevel = Floating.GetLiquidLevel(point, 1f, (LiquidType)0); float groundHeight = ZoneSystem.instance.GetGroundHeight(point); if (waterLevel - groundHeight >= 2f) { return true; } } point = Vector3.zero; waterLevel = 0f; return false; } private static FishInfo Pick(List<FishInfo> candidates, string bait) { float num = 0f; float[] array = new float[candidates.Count]; for (int i = 0; i < candidates.Count; i++) { float num2 = Mathf.Max(0.05f, candidates[i].Baits[bait]); if (!FishData.IsCaught(candidates[i])) { num2 *= FishTrackerPlugin.UncaughtWeight.Value; } array[i] = num2; num += num2; } float num3 = Random.Range(0f, num); for (int j = 0; j < candidates.Count; j++) { num3 -= array[j]; if (num3 <= 0f) { return candidates[j]; } } return candidates[candidates.Count - 1]; } private static int RollLevel() { int i; for (i = 1; i < FishTrackerPlugin.MaxLevel.Value; i++) { if (!(Random.value < FishTrackerPlugin.LevelUpChance.Value)) { break; } } return i; } } internal class FishInfo { public GameObject Prefab; public Fish Fish; public string ItemName; public Biome Biomes; public readonly Dictionary<string, float> Baits = new Dictionary<string, float>(); } internal static class FishData { internal const string FishermanId = "GrindFish"; private static readonly List<FishInfo> NoFish = new List<FishInfo>(); private static List<FishInfo> s_fish; private static readonly Dictionary<string, FishInfo> s_byItem = new Dictionary<string, FishInfo>(); private static readonly Dictionary<string, List<FishInfo>> s_byBait = new Dictionary<string, List<FishInfo>>(); private static bool s_biomesLoaded; private static float s_nextBiomeTry; private static Achievement s_fisherman; internal static Achievement Fisherman { get { if (!((Object)(object)s_fisherman != (Object)null)) { return s_fisherman = AchievementStats.Find("GrindFish"); } return s_fisherman; } } internal static List<FishInfo> All { get { if (s_fish == null || s_fish.Count == 0) { Build(); } if (!s_biomesLoaded && Time.time >= s_nextBiomeTry) { s_nextBiomeTry = Time.time + 5f; LoadBiomes(); } return s_fish; } } internal static bool IsCaught(FishInfo fish) { return AchievementStats.Has(AchievementStats.StatsFor(Fisherman)?.m_pickableStats, fish.Fish.m_name); } internal static FishInfo ByItemName(string itemName) { if (All.Count == 0) { return null; } s_byItem.TryGetValue(itemName, out var value); return value; } internal static List<FishInfo> BitersOf(string baitName) { if (All.Count == 0) { return NoFish; } if (!s_byBait.TryGetValue(baitName, out var value)) { return NoFish; } return value; } internal static int CaughtCount() { return AchievementStats.CountDone(AchievementStats.Keys(Fisherman?.m_pickableTriggers), AchievementStats.StatsFor(Fisherman)?.m_pickableStats); } internal static int TotalCount() { return AchievementStats.Keys(Fisherman?.m_pickableTriggers).Count; } private static void Build() { s_fish = new List<FishInfo>(); s_byItem.Clear(); s_byBait.Clear(); if ((Object)(object)ObjectDB.instance == (Object)null) { return; } foreach (GameObject item in ObjectDB.instance.m_items) { Fish val = (((Object)(object)item != (Object)null) ? item.GetComponent<Fish>() : null); ItemDrop val2 = (((Object)(object)item != (Object)null) ? item.GetComponent<ItemDrop>() : null); if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null) { continue; } FishInfo fishInfo = new FishInfo { Prefab = item, Fish = val, ItemName = val2.m_itemData.m_shared.m_name }; foreach (BaitSetting bait in val.m_baits) { if ((Object)(object)bait.m_bait != (Object)null) { fishInfo.Baits[bait.m_bait.m_itemData.m_shared.m_name] = bait.m_chance; } } s_fish.Add(fishInfo); s_byItem[fishInfo.ItemName] = fishInfo; foreach (string key in fishInfo.Baits.Keys) { if (!s_byBait.TryGetValue(key, out var value)) { value = (s_byBait[key] = new List<FishInfo>()); } value.Add(fishInfo); } } s_biomesLoaded = false; } private static void LoadBiomes() { //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) SpawnSystemList[] array = Resources.FindObjectsOfTypeAll<SpawnSystemList>(); if (array.Length == 0) { return; } s_biomesLoaded = true; SpawnSystemList[] array2 = array; for (int i = 0; i < array2.Length; i++) { foreach (SpawnData spawn in array2[i].m_spawners) { if (!((Object)(object)spawn?.m_prefab == (Object)null) && spawn.m_enabled) { FishInfo fishInfo = s_fish.Find((FishInfo f) => ((Object)f.Prefab).name == ((Object)spawn.m_prefab).name); if (fishInfo != null) { fishInfo.Biomes |= spawn.m_biome; } } } } } } [HarmonyPatch] internal static class FishingIndicator { private const float HookWindow = 0.5f; private static readonly Color WaitColor = new Color(0.85f, 0.85f, 0.85f, 0.8f); private static readonly Color PullColor = new Color(0.4f, 1f, 0.4f, 1f); private static readonly Color HoldColor = new Color(1f, 0.35f, 0.3f, 1f); private static readonly FieldRef<FishingFloat, Fish> s_nibbler = AccessTools.FieldRefAccess<FishingFloat, Fish>("m_nibbler"); private static readonly FieldRef<FishingFloat, float> s_nibbleTime = AccessTools.FieldRefAccess<FishingFloat, float>("m_nibbleTime"); private static readonly FieldRef<FishingFloat, ZNetView> s_floatView = AccessTools.FieldRefAccess<FishingFloat, ZNetView>("m_nview"); private static TMP_Text s_label; [HarmonyPostfix] [HarmonyPatch(typeof(Hud), "Awake")] private static void HudAwake(Hud __instance) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) RectTransform rectTransform = ((Graphic)__instance.m_crosshair).rectTransform; GameObject val = new GameObject("FishTracker_FishingIndicator", new Type[2] { typeof(RectTransform), typeof(TextMeshProUGUI) }); RectTransform val2 = (RectTransform)val.transform; ((Transform)val2).SetParent(((Transform)rectTransform).parent, false); val2.anchorMin = rectTransform.anchorMin; val2.anchorMax = rectTransform.anchorMax; val2.pivot = new Vector2(0.5f, 1f); val2.sizeDelta = new Vector2(400f, 40f); val2.anchoredPosition = rectTransform.anchoredPosition + new Vector2(0f, -40f); s_label = (TMP_Text)(object)val.GetComponent<TextMeshProUGUI>(); s_label.font = ((TMP_Text)__instance.m_hoverName).font; s_label.fontSharedMaterial = ((TMP_Text)__instance.m_hoverName).fontSharedMaterial; s_label.fontSize = 26f; s_label.fontStyle = (FontStyles)1; s_label.alignment = (TextAlignmentOptions)258; ((Graphic)s_label).raycastTarget = false; val.SetActive(false); } [HarmonyPostfix] [HarmonyPatch(typeof(Hud), "Update")] private static void HudUpdate() { //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)s_label == (Object)null) { return; } FishingFloat val = (FishTrackerPlugin.FishingIndicator.Value ? FindLocalFloat() : null); if ((Object)(object)val == (Object)null || !val.IsInWater()) { ((Component)s_label).gameObject.SetActive(false); return; } Fish val2 = val.GetCatch(); if ((Object)(object)val2 != (Object)null) { if (val2.IsEscaping()) { Show("Fish is fighting, wait", HoldColor); } else { Show("Reel in", PullColor); } } else if ((Object)(object)s_nibbler.Invoke(val) != (Object)null && Time.time - s_nibbleTime.Invoke(val) < 0.5f) { Show("Bite! Reel in to hook it", PullColor); } else { Show("Wait for a bite", WaitColor); } } private static void Show(string text, Color color) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) s_label.text = text; ((Graphic)s_label).color = color; ((Component)s_label).gameObject.SetActive(true); } private static FishingFloat FindLocalFloat() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return null; } ZDOID zDOID = ((Character)localPlayer).GetZDOID(); long userID = ((ZDOID)(ref zDOID)).UserID; foreach (FishingFloat allInstance in FishingFloat.GetAllInstances()) { ZNetView val = s_floatView.Invoke(allInstance); if ((Object)(object)val != (Object)null && val.IsValid() && val.GetZDO().GetLong(ZDOVars.s_rodOwner, 0L) == userID) { return allInstance; } } return null; } } [HarmonyPatch] internal static class HandCatch { private static readonly HashSet<GameObject> s_rodCatches = new HashSet<GameObject>(); [HarmonyPrefix] [HarmonyPatch(typeof(FishingFloat), "Catch")] private static void RodCatch(Fish fish) { s_rodCatches.RemoveWhere((GameObject go) => (Object)(object)go == (Object)null); if ((Object)(object)fish != (Object)null) { s_rodCatches.Add(((Component)fish).gameObject); } } [HarmonyPrefix] [HarmonyPatch(typeof(Humanoid), "Pickup")] private static void PickupPrefix(Humanoid __instance, GameObject go, out Fish __state) { __state = null; if (FishTrackerPlugin.HandCatchCounts.Value && !((Object)(object)go == (Object)null) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && !s_rodCatches.Remove(go)) { Fish component = go.GetComponent<Fish>(); if ((Object)(object)component != (Object)null && (Object)(object)FishingFloat.FindFloat(component) != (Object)null) { __state = component; } } } [HarmonyPostfix] [HarmonyPatch(typeof(Humanoid), "Pickup")] private static void PickupPostfix(bool __result, Fish __state) { if (__result && !((Object)(object)__state == (Object)null) && !((Object)(object)Game.instance == (Object)null)) { Game.instance.GetPlayerProfile().IncrementStatPickable(__state.GetHoverName(), 1f, false); Game.instance.IncrementPlayerStat((PlayerStatType)160, 1f, false); ItemDrop component = ((Component)__state).GetComponent<ItemDrop>(); if ((Object)(object)component != (Object)null && component.m_itemData.m_quality <= 6) { Game.instance.IncrementPlayerStat((PlayerStatType)(161 + component.m_itemData.m_quality), 1f, false); } } } } [BepInPlugin("com.koendertjh.fishtracker", "FishTracker", "1.1.0")] public class FishTrackerPlugin : BaseUnityPlugin { public const string ModGuid = "com.koendertjh.fishtracker"; public const string ModName = "FishTracker"; public const string ModVersion = "1.1.0"; internal static ManualLogSource Log; internal static ConfigEntry<bool> TooltipHints; internal static ConfigEntry<bool> HideUnknownFish; internal static ConfigEntry<bool> ChumEnabled; internal static ConfigEntry<int> BaitPerChum; internal static ConfigEntry<int> FishPerChum; internal static ConfigEntry<float> UncaughtWeight; internal static ConfigEntry<float> LevelUpChance; internal static ConfigEntry<int> MaxLevel; internal static ConfigEntry<bool> TetraInDeepNorth; internal static ConfigEntry<bool> FishingIndicator; internal static ConfigEntry<bool> HandCatchCounts; private Harmony _harmony; private void Awake() { //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Expected O, but got Unknown //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Expected O, but got Unknown //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Expected O, but got Unknown //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Expected O, but got Unknown //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Expected O, but got Unknown //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; TooltipHints = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - Tooltips", "TooltipHints", true, "Fish tooltips say when you haven't caught the fish yet; bait tooltips list the fish that bite on it."); HideUnknownFish = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - Tooltips", "HideUnknownFish", false, "Bait tooltips show '???' for fish you have never had, instead of their name."); ChumEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - Chum", "Enabled", true, "Add chum, crafted by hand from fishing bait. Needs a restart. Chum disappears from inventories and chests when this is off or the mod is removed."); BaitPerChum = ((BaseUnityPlugin)this).Config.Bind<int>("2 - Chum", "BaitPerChum", 5, new ConfigDescription("Bait needed for one chum. Needs a restart.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 50), Array.Empty<object>())); FishPerChum = ((BaseUnityPlugin)this).Config.Bind<int>("2 - Chum", "FishPerChum", 3, new ConfigDescription("Fish that show up for one chum.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 10), Array.Empty<object>())); UncaughtWeight = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Chum", "UncaughtWeight", 3f, new ConfigDescription("Fish you haven't caught yet are this many times more likely to show up.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 20f), Array.Empty<object>())); LevelUpChance = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Chum", "LevelUpChance", 0.25f, new ConfigDescription("Chance for a chum fish to gain a star, rolled again for each star.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); MaxLevel = ((BaseUnityPlugin)this).Config.Bind<int>("2 - Chum", "MaxLevel", 4, new ConfigDescription("Highest fish level from chum. Level 4 (3 stars) is what A Catch Worthy of Njord needs.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 5), Array.Empty<object>())); TetraInDeepNorth = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - Chum", "TetraInDeepNorth", false, "Chum can also bring Tetra (a Mountain fish) in the Deep North, where the snowy peaks count as Deep North instead of Mountain."); FishingIndicator = ((BaseUnityPlugin)this).Config.Bind<bool>("3 - Fishing", "Indicator", true, "Show under the crosshair when to reel in (block) while fishing: when a fish bites, and while a hooked fish is calm. Says to wait while a hooked fish fights, when reeling costs double stamina."); HandCatchCounts = ((BaseUnityPlugin)this).Config.Bind<bool>("3 - Fishing", "HandCatchCounts", false, "Picking up a fish by hand while it is hooked on a fishing line counts as catching it, like reeling it in: for The Fisherman, A Catch Worthy of Njord and the fish caught stats."); _harmony = new Harmony("com.koendertjh.fishtracker"); _harmony.PatchAll(typeof(FishTrackerPlugin).Assembly); } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } [HarmonyPatch(typeof(ItemData), "GetTooltip", new Type[] { typeof(ItemData), typeof(int), typeof(bool), typeof(float), typeof(int), typeof(bool) })] internal static class TooltipPatch { private const string HintColor = "#ffb347"; private const string ProgressColor = "#a0a0a0"; private static void Postfix(ItemData item, ref string __result) { if (!FishTrackerPlugin.TooltipHints.Value || item?.m_shared == null || (Object)(object)Game.instance == (Object)null || (Object)(object)ObjectDB.instance == (Object)null) { return; } string name = item.m_shared.m_name; FishInfo fishInfo = FishData.ByItemName(name); if (fishInfo != null) { StringBuilder stringBuilder = new StringBuilder(__result); if (!FishData.IsCaught(fishInfo)) { stringBuilder.Append("\n\n<color=#ffb347>You haven't caught this fish yet.</color>"); } if ((Object)(object)FishData.Fisherman != (Object)null) { stringBuilder.Append("\n<color=#a0a0a0>" + Localization.instance.Localize(FishData.Fisherman.m_name) + ": " + $"{FishData.CaughtCount()} / {FishData.TotalCount()}</color>"); } __result = stringBuilder.ToString(); return; } List<FishInfo> list = FishData.BitersOf(Chum.BaitOf(name) ?? name); if (list.Count == 0) { return; } StringBuilder stringBuilder2 = new StringBuilder(__result); stringBuilder2.Append("\n\nFish that bite:"); Player localPlayer = Player.m_localPlayer; foreach (FishInfo item2 in list) { bool flag = FishData.IsCaught(item2); string text = ((flag || ((Object)(object)localPlayer != (Object)null && localPlayer.IsMaterialKnown(item2.ItemName)) || !FishTrackerPlugin.HideUnknownFish.Value) ? Localization.instance.Localize(item2.Fish.m_name) : "???"); stringBuilder2.Append(flag ? ("\n " + text) : ("\n <color=#ffb347>" + text + " (not caught yet)</color>")); } __result = stringBuilder2.ToString(); } } internal static class PluginInfo { public const string Version = "1.1.0"; } }